Hatena::Groupptech

ぷちてく RSSフィード

Archive
 
ProfileProfile

2017-04-05

iframeがChromiumのXSS Filterに引っかかる

07:38

さっき上げた記事、プレビューしようとしたら Chromium が「pass, カード情報が盗まれるぞ」みたいな事言ってきて仕方なく Firefox で投稿。

はてなダイアリーはてなグループ日記で iframe 貼ると再現した。「ニコニコ大百科でも起こる」とのこと。ツイートしてくれた方ありがとうございます。

さっき貼ったHatena::Let

<iframe border="0" frameborder="0" height="130" src="http://let.st-hatelabo.com/noromanba/let.iframe?embed=1&code_id=hLHW56bVtuAQ" width="500"></iframe>

Youtubeでもなるのでどうしようもない。

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/HhDTdd7VTY0" frameborder="0" allowfullscreen></iframe>

incognito でも試したので拡張機能のせいではない。

ERR_BLOCKED_BY_XSS_AUDITOR

f:id:noromanba:20170405075942p:image

This page isn’t working

Chrome detected unusual code on this page and blocked it to protect your personal information (for example, passwords, phone numbers, and credit cards).
Try visiting the site's homepage.
ERR_BLOCKED_BY_XSS_AUDITOR
http://d.hatena.ne.jp/noromanba/edit

代替

影響大きそうなのでダイアリーにも一般人向け書いた。

動画系だと API 使えれば img と a タグでどうとでもなる。

<a href="https://www.youtube.com/watch?v=Y4f1cdNv_M8" target="_blank">
  <img src="https://img.youtube.com/vi/Y4f1cdNv_M8/sddefault.jpg" alt="thumbnail" title="東京事変 - 空が鳴っている - YouTube">
  </a>
[https://www.youtube.com/watch?v=Y4f1cdNv_M8:title]
iframeあるとChromeで記事更新できないかも - (有)掛軸裏スキマ産業

こんな感じ。軽くていい。

thumbnail

東京事変 - 空が鳴っている - YouTube

参考。

カードみたいなやつはキャプチャダルいので、なんかサービスあるんじゃないすかね。embed.ly の画像版みたいな物体とか。

元も子もないけど iframe 重いだけのゴミだと思ってるので使えない方がうれしい。

X-XSS-Protection

HTTP ヘッダ の X-XSS-Protection が制御に干渉するようだけど、

header("X-XSS-Protection: 0");
https://stackoverflow.com/questions/17016960/chromiums-xss-auditor-refused-to-execute-a-script#17017013

これ何かというと、ブラウザに「XSS フィルタ切れ」と言ってるのでマトモな解決方法にならない。

X-XSS-Protection: 0
X-XSS-Protection: 1
X-XSS-Protection: 1; mode=block
X-XSS-Protection: 1; report=<reporting-uri>
0
    Disables XSS filtering.
1
    Enables XSS filtering (usually default in browsers). If a cross-site scripting attack is detected, the browser will sanitize the page (remove the unsafe parts).
1;mode=block
    Enables XSS filtering. Rather than sanitizing the page, the browser will prevent rendering of the page if an attack is detected.
1; report=<reporting-URI>  (Chromium only)
    Enables XSS filtering. If a cross-site scripting attack is detected, the browser will sanitize the page and report the violation. This uses the functionality of the CSP report-uri directive to send a report.
X-XSS-Protection - HTTP | MDN

YouTube はきちんとしてるでしょ、と思ったらやっぱりやってた。

$ HEAD https://www.youtube.com/watch?v=Y4f1cdNv_M8 | grep -i xss
X-XSS-Protection: 1; mode=block; report=https://www.google.com/appserve/security-bugs/log/youtube
$

この辺見るのが厳しくなったのかな、というふわっとした感じ。

何か書いた直後から検索経由でアクセスすごい飛んできてて(当社比)、こりゃ誰も書いてなさそう…と思いました。



Environment

Chromium 57.0.2987.98 (Developer Build) Built on Ubuntu , running on Ubuntu 16.04 (32-bit)
Revision a6a06b78087c9fdb4b12fe0ac1b87fdc10179f8b
OS Linux
JavaScript V8 5.7.492.63
Flash 25.0.0.127 /usr/lib/adobe-flashplugin/libpepflashplayer.so
User Agent Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36
Command Line /usr/lib/chromium-browser/chromium-browser --ppapi-flash-path=/usr/lib/adobe-flashplugin/libpepflashplayer.so --ppapi-flash-version=25.0.0.127 --enable-pinch --flag-switches-begin --overscroll-history-navigation=0 --disable-smooth-scrolling --disable-features=CredentialManagementAPI,MaterialDesignHistory --flag-switches-end
Executable Path /usr/lib/chromium-browser/chromium-browser
Profile Path /home/noro/.config/chromium/Default

> chrome://version/

$ apt policy chromium-browser
chromium-browser:
  Installed: 57.0.2987.98-0ubuntu0.16.04.1276
  Candidate: 57.0.2987.98-0ubuntu0.16.04.1276
  Version table:
 *** 57.0.2987.98-0ubuntu0.16.04.1276 500
        500 http://ppa.launchpad.net/canonical-chromium-builds/stage/ubuntu xenial/main i386 Packages
        100 /var/lib/dpkg/status
     56.0.2924.76-0ubuntu0.16.04.1268 500
        500 http://ftp.jaist.ac.jp/pub/Linux/ubuntu xenial-updates/universe i386 Packages
        500 http://ftp.jaist.ac.jp/pub/Linux/ubuntu xenial-security/universe i386 Packages
     49.0.2623.108-0ubuntu1.1233 500
        500 http://ftp.jaist.ac.jp/pub/Linux/ubuntu xenial/universe i386 Packages
Experimental Credential Manager API

Command Line のところ見ていて、flag で --disable-features=CredentialManagementAPI,MaterialDesignHistory となっていたので、

"Experimental Credential Manager API" 切ってるのが怪しいかと思い Enable にしてみた。Command Line から消えてるの確認。

再実験で同じく XSS Auditor でブロックされる結果に。戻した。

f:id:noromanba:20170406010403p:image

> chrome://flags/#enable-credential-manager-api

関係無さそう。

トラックバック - http://ptech.g.hatena.ne.jp/noromanba/20170405

2017-04-04

Noto Serif CJK のダウンロード先がSansになってるの直す

05:26

ようやく "Region-specific Subset OpenType/CFF (Subset OTF)" Serif の リンクが修正された。

$ HEAD https://www.google.com/get/noto/help/cjk/ | grep -i last
Last-Modified: Wed, 05 Apr 2017 18:30:00 GMT
$ date -d "Wed, 05 Apr 2017 18:30:00 GMT"
Thu Apr  6 03:30:00 JST 2017

Last-Modified 信用すると、

$ date -d "@1491337619"       # 記事の epoch
Wed Apr  5 05:26:59 JST 2017

この記事出してから24H弱くらいかかったみたい。

https://noto-website.storage.googleapis.com/pkgs/NotoSerifJP.zip

以下は修正前、Noto*Sans*JP.zip に向いてたリリース時の話。


話題の明朝フォント、CJK用ページのリンクが Sans に向いてておかしい。

最下段 "Region-specific Subset OpenType/CFF (Subset OTF)" のところ、Serif 気取ってますが実際は Sans がダウンロードされる。致命的。

修正書いた、名前はシャレです。Bookmarklet/ブックマークレット

isNotoSerif! - Hatena::Let

UserScript/ユーザースクリプト

https://gist.github.com/noromanba/a479fa5bc3c4619383ee62f6af74c923/raw/isnotoserif.user.js

現状かなり手抜き。

(() => {
    'use strict';

    // XXX use XPath, smart
    // TODO assertion
    const subsetOTF = [...document.body.querySelectorAll('.cjk-downloads')].pop();
    const subsetOTFSerif = [...subsetOTF.querySelectorAll('tbody tr')].pop();

    Array.from(subsetOTFSerif.querySelectorAll([
      'a[href*="/NotoSans"]'
    ]), serif => serif.href = serif.href.replace(/\/NotoSans/, '/NotoSerif'));
})();
http://let.hatelabo.jp/noromanba/let/hLHW56bVtuAQ/rev/hLHW57nTjpV6

以下で指摘しようとしたら Google Plus に join しそうになってメッチャ不快だったので、誰かコメントしといて下さい。

あるいはTwitterな人、@ 殴っといて下さい。

詳細

"Region-specific Subset OpenType/CFF (Subset OTF)" のところ、

Serif
NotoSerifJP-[weight].otf
NotoSerifKR-[weight].otf
NotoSerifSC-[weight].otf
NotoSerifTC-[weight].otf

28 OTF font files in total: 4 languages × 7 weights.

https://www.google.com/get/noto/help/cjk/

間違って *Sans* になってる。

https://noto-website.storage.googleapis.com/pkgs/NotoSansJP.zip

実際はこっち。

https://noto-website.storage.googleapis.com/pkgs/NotoSerifJP.zip

「サイトリニューアルしたのに、Google でもこんなしょーもないコピペ生産かよ」と思いました。

アドレス適当に叩いたらちゃんとしたの落ちてきた。

noro@iron:~/.local/share/fonts$ wget https://noto-website.storage.googleapis.com/pkgs/NotoSerifJP.zip
--2017-04-05 03:48:32--  https://noto-website.storage.googleapis.com/pkgs/NotoSerifJP.zip
Resolving noto-website.storage.googleapis.com (noto-website.storage.googleapis.com)... 216.58.197.208
Connecting to noto-website.storage.googleapis.com (noto-website.storage.googleapis.com)|216.58.197.208|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 36195581 (35M) [application/zip]
Saving to: ‘NotoSerifJP.zip’

中身。

noro@iron:~/.local/share/fonts$ lsar -l NotoSerifJP.zip
NotoSerifJP.zip: Zip
     Flags  File size   Ratio  Mode  Date       Time   Name
     =====  ==========  =====  ====  ========== =====  ====
  0. -----        4301  56.7%  Defl  2017-04-03 13:42  LICENSE_OFL.txt
  1. -----     6347760  16.2%  Defl  2017-04-03 13:40  NotoSerifJP-Black.otf
  2. -----     6445296  15.7%  Defl  2017-04-03 13:40  NotoSerifJP-Bold.otf
  3. -----     5683004  17.4%  Defl  2017-04-03 13:40  NotoSerifJP-ExtraLight.otf
  4. -----     6102284  17.1%  Defl  2017-04-03 13:40  NotoSerifJP-Light.otf
  5. -----     6257896  16.3%  Defl  2017-04-03 13:40  NotoSerifJP-Medium.otf
  6. -----     6183224  16.6%  Defl  2017-04-03 13:40  NotoSerifJP-Regular.otf
  7. -----     6292656  16.0%  Defl  2017-04-03 13:40  NotoSerifJP-SemiBold.otf
  8. -----         308  27.6%  Defl  2017-04-03 13:41  README
(Flags: D=Directory, R=Resource fork, L=Link, E=Encrypted, @=Extended attributes)
(Mode: Defl=Deflate)
noro@iron:~/.local/share/fonts$

この辺はおかしくない。

トラックバック - http://ptech.g.hatena.ne.jp/noromanba/20170404

2017-04-01

Hatena::Letの後継作り

05:14

いよいよボロい。誰か後継作らないかなと数年ボーッとしてる間に Heroku の 24/7 が死んだので、Google Cloud とか Azure みたいな無料系で回していく感じにしたい。

みんな大好き node.js や、RubyPython 辺りが人集まりやすそうと思ってる。

トラックバック - http://ptech.g.hatena.ne.jp/noromanba/20170401

2017-03-05

element.click() が効かない時

04:17

ハマりそうなやつ。元記事はいわゆる Callback Hell 系の文脈

検証コードで安直に .click() したら効かなかった。

body = window.document.body;
body.onclick = () => {
  console.log('outer');
  body.onclick = () => {
    console.log('inner');
  };
  body.click();
};
body.click();
// -> outer
http://ptech.g.hatena.ne.jp/noromanba/20170302/1488491168#element-click-failed

内側 .click() 動かない。

回避策

a-kuma3

.dispatchEvent(MouseEvent) だと、内側も発火した >Firefox

const do_click = (e) => {
  const clickEvent = new MouseEvent("click", {
    view: window,
 });
 e.dispatchEvent(clickEvent);
};

body = window.document.body;
body.onclick = () => {
  console.log('outer');
  body.onclick = () => {
    console.log('inner');
  };
  do_click(body);
};
do_click(body);

<snip>

.click()setTimeout() でずらしても、発火した。

setTimeout(() => body.click(), 0)
http://ptech.g.hatena.ne.jp/noromanba/20170302#c1488502400

確かに両方返ってくる。

// -> outer
// -> inner

手元で試した setTimeout 版。

body = window.document.body;
body.onclick = () => {
  console.log('outer');
  body.onclick = () => {
    console.log('inner');
  };
  setTimeout(() => body.click(), 0);
};
body.click();
// -> outer
// -> undefined
// -> inner

これも両方動く。

感想

noromanba

> a-kuma3

検証 thx です。.dispatchEvent(MouseEvent) と timer 、確かに。Chromium 56.0.2924.76。

dblclick で動くわけでもないので、 ブラウザ側の tick/timer/job queu(e)ing あたりか .click() の仕様とか内部で気を効かせてそう。

http://ptech.g.hatena.ne.jp/noromanba/20170302#c1488736902

連打は?

noromanba

body = window.document.body;
body.onclick = () => console.log('ouch!');
for (i = 0; i < 10; i+=1) {
  body.click();
}
// -> (10) ouch!

えっ、ネストか

http://ptech.g.hatena.ne.jp/noromanba/20170302#c1488738344

書いたみたいに .click() 内部の debounce (throttle) とか、tick/timer/job queu(e)ing かと思ったんだけど、なんなんすかね。

どっかに書いてありそう。


環境

Chromium56.0.2924.76 (Developer Build) Built on Ubuntu , running on Ubuntu 16.04 (32-bit)
Revision314da7cc1e56fc9fa9271bac2b029922feb4b6f2
OSLinux
JavaScriptV8 5.6.326.42
User AgentMozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/56.0.2924.76 Chrome/56.0.2924.76 Safari/537.36
$ apt policy chromium-browser
chromium-browser:
  Installed: 56.0.2924.76-0ubuntu1.16.04.1271
  Candidate: 56.0.2924.76-0ubuntu1.16.04.1271
  Version table:
 *** 56.0.2924.76-0ubuntu1.16.04.1271 500
        500 http://ppa.launchpad.net/canonical-chromium-builds/stage/ubuntu xenial/main i386 Packages
        100 /var/lib/dpkg/status
トラックバック - http://ptech.g.hatena.ne.jp/noromanba/20170305

2017-03-02

同イベントのハンドラがネスト構造なコード

06:46

最初に断っておくと、ネストを積極的に使う理由はないので極力避けましょう。しかし読む場合はあるし、書かなければいけないこともあるでしょう。つらい。

外側のハンドラ末尾で再度イベントが発生、内側のハンドラが呼ばれる、という構造でハマったのを書いた。解決したので解説みたいなものを書いていく。

外側ハンドラ末尾で再発生してるイベントを見落とした結果、理解出来ない挙動に *見えていた* という話で、再現失敗してたところ、a-kuma3 さんがコメントしてくれて気付いた。

理解と再現出来た。ただ、自分の検証コードで再現再失敗してまたわからない挙動が出てきてしまった。ウケる。

言葉ではわかりづらいので実際の例見てもらった方が早い。a-kuma3 さんがコメント後、さらにハイクしてくれたのがミニマムでわかりやすいので引用。ハイクの仕様で全角スペースなところを半角変換したのでコピペ再現出来る。

onload = なのは元コードがそうだったから。

xhr = new XMLHttpRequest();
xhr.open('GET', location.href);
xhr.onload = () => {
  console.log('outer');
  xhr.onload = () => {
    console.log('inner');
  };
  xhr.open('GET', location.href);   // もう一回 open
  xhr.send();
};
xhr.send();
// -> outer
// -> inner
>|javascript|xhr = new XMLHttpReque... - JavaScript - a-kuma3 - はてなハイク

順序は、

  1. 外側のハンドラが登録されるが何もしない
  2. 最後の xhr.send();load イベント発生
  3. 外側のハンドラが動く
    • xhr.onload を内側のハンドラが上書きするが何もしない
  4. 外側のハンドラ末尾の xhr.send(); で再度 load イベント発生
  5. 上書きした内側のハンドラが動く

という流れ。イベントドリブン初心者は理解キツそう。

このように外側と同じく内側も同じ順に書くと、自然。

xhr = new XMLHttpRequest();
xhr.open('GET', location.href);
xhr.onload = () => {
  console.log('outer');
  xhr.open('GET', location.href);
  xhr.onload = () => {
    console.log('inner');
  };
  xhr.send();
};
xhr.send();

open() -> onload -> send()

open() -> onload -> send()

addEventListener() ならこんな感じ。ちょっと長くなる。

xhr = new XMLHttpRequest();
xhr.open('GET', location.href);

outer = () => {
  console.log('outer');
  xhr.removeEventListener('load', outer);
  xhr.open('GET', location.href);
  xhr.addEventListener('load', () => {
    console.log('inner');
  });
  xhr.send();
};

xhr.addEventListener('load', outer);
xhr.send();
// -> outer
// -> inner

removeEventListener() 無いとハンドラが無限ループするので注意。

ネストしない

大抵の場合、こういう感じっぽくフラットに書ければ混乱しづらい。

xhr = new XMLHttpRequest();
xhr.open('GET', location.href);
xhr.addEventListener('load', () => {
  console.log('I was outer');
  // ...
});
xhr.addEventListener('load', () => {
  console.log('I was inner');
  // ...
});
xhr.send();
// -> I was outer
// -> I was inner

しかしネストしてたということは、逐一 fetch しなければいけない状況があるはずで、これでは動かないどうしよう…。

といった背景も一因になって DeferredPromise 等色々生まれてるので適宜やっていきましょう。

再現再失敗

ハイクで返事貰う前、「XHR より click イベントがお手軽そう」と思ってこんなコードを書いたら違うカルマを背負った。

body = window.document.body;
body.onclick = () => {
  console.log('outer');
  body.onclick = () => {
    console.log('inner');
  };
  body.click();
};
body.click();
// -> outer

アイエエエ!?」.click() が マズイのか、キャプチャリング・バブリングとかフェーズの問題なのか、単純にコードが間違ってるのか。

すぐ時間が無くなってとりあえずあきらめた次第。


続き書いた。

a-kuma3a-kuma32017/03/03 09:53.dispatchEvent(MouseEvent) だと、内側も発火した >Firefox

const do_click = (e) => {
 const clickEvent = new MouseEvent("click", {
  view: window,
 });
 e.dispatchEvent(clickEvent);
};

body = window.document.body;
body.onclick = () => {
 console.log('outer');
 body.onclick = () => {
  console.log('inner');
 };
 do_click(body);

};
do_click(body);


.click() を setTimeout() でずらしても、発火した。

setTimeout(() => body.click(), 0)

unaristunarist2017/03/03 21:57ちなみに最初はインスタンス使いまわせないと思っていて、コピペしてインスタンスだけ変えた、つもりが変わってなくて使いまわせることに気づいた感じですね。
# でも気持ち悪いなーと思ってたら見事に勘違いされたので、ネタ以外では使わないようにしよう…

noromanbanoromanba2017/03/06 03:01> a-kuma3
検証 thx です。`.dispatchEvent(MouseEvent)` と timer 、確かに。Chromium 56.0.2924.76。

body = window.document.body;
body.onclick = () => {
console.log('outer');
body.onclick = () => {
console.log('inner');
};
settimeout(() => body.click(), 0);
};
body.click();

`dblclick` で動くわけでもないので、 ブラウザ側の tick/timer/job queu(e)ing あたりか .click() の仕様とか内部で気を効かせてそう。

noromanbanoromanba2017/03/06 03:13> unarist
> 使いまわせることに気づいた感じ
なんと…。小さいとライブラリの導入もアレなんで、もしやるなら標準の Promise.all Promise#then するのがいいのかなー。「フラット化どうよ」みたいな声もありますが、気にせずやっていきましょう

noromanbanoromanba2017/03/06 03:25body = window.document.body;
body.onclick = () => console.log('ouch!');
for (i = 0; i < 10; i+=1) {
body.click();
}
// -> (10) ouch!

えっ、ネストか


Copylight (c) noromanba 2012-2017