
9,500 文字
これまでに、あなたがソフトウェア開発者としてのキャリアに疑問を抱くほど、本当にこの仕事は価値があるのかと考えさせられるような、ひどいコードを見たことがありますか?私はTwitterで壁紙として見かけたのですが、言葉になりません。数日前に見てから考え続けていて、一人で黙って苦しみ続けることもできますが、代わりに皆さんも一緒にこの穴に引きずり込もうと思います。
このコードを一行ずつ見ていきましょう。また、このコードがどこから来たのか、なぜ存在するのか、そしてどのようにしてここに至ったのかという歴史についても見ていきます。「if true equals true」から奇妙なインターネットの使用例まで、掘り下げることがたくさんありますが、まずは今日のスポンサーからの一言です。
今日のスポンサーはbrowser baseで、私はこの会社が大好きで投資もしています。これはAIのためのウェブブラウザですが、それは一体どういう意味でしょうか?これは、ChromiumとPlayrightのカオスを管理するサービスで、従来のPlayrightやPuppeteer、あるいは彼らが構築した素晴らしいものすべてをAPIのように扱うことができます。
ここでブラウザを開き、コマンドエンターを押すだけで、たくさんのクレイジーなことを指示できます。Hacker Newsに行って、Googleに行って最初の結果をクリックするように頼むことができ、コードを生成して実行します。しかしこれは製品ではなく、製品のデモです。製品は、Playrightによって照会されているブラウザのクラウドホスティングです。
これをクリックすると、window.playwright.chromium.connectOverCDPのコードが生成され、そのリモートChromiumインスタンスに接続され、すぐに動作します。とても便利ですが、browser baseを使用せずに使える無料のオープンソースパッケージのstagehandを使用するとさらに便利になります。
特定のページに移動して、要素に移動してクリックをトリガーするのではなく、「貢献者をクリックする」と指示し、「トップ貢献者を抽出する」と指示して、Zodスキーマを与えるだけで(しばらく前からご存知の通り、これは最高の検証ライブラリです)、このデータを自動的に型安全に取得できます。なんて素晴らしいんでしょう!
AIを実際のコードで論理的で単純で有用なことを行うために使用できます。以前にPlayrightでこれを書くのは…楽しくありませんでした。やりたいことを言って、指示を与え、スキーマを与えるだけで済むのに比べて、どれだけ多くの作業が必要かわかりますよね。言葉では言い表せないほど便利です。
スポンサーのbrowser baseに感謝します。s.l/browserBasで今すぐチェックしてください。また、先ほど言及したstagehandもチェックしてください。
以前に言及したように、誰かが開発者のコードや壁紙として投稿したのを見かけました。そして私の研究者のGabrielがそれを引用リツイートして批判し、私も「ああ、これはひどい」と思い、自分でも批判したツイートを投稿したところ、それなりにバイラルになりましたが、考え続けていました。
特に、最後のここのshow login failedという部分以外は全て構文的に正しかったため、どこから来たのか本当に理解したかったのです。これは有効な構文ではありませんが、他のすべては正しかったのです。削除されたプログラミングホラーの投稿からこのソースを見つけ、web archiveでも見つけました。そして以前は画像が機能していました。
よし、また機能していますね。そして私の知る限り、これが元のコードに最も近いものです。なぜなら、showの奇妙な部分が削除され、他のコードは同一だと確信しているからです。「Pi service equal select from bear count length i++ return true」はとても奇妙です。この部分だけを変更し、このlogin failedを追加するのは…私にはどうしてそうなったのかわかりません。本当にわかりません。
唯一見つけられなかったのは、このlogin failedがこの酷いコピペコードに追加され、現在の場所に配置されることになった経緯です。しかし、まずはコード自体を分解してみましょう。一行ずつ見ていきましょう。
最初に、Sublime Textの541行目に「to do put this in a different file」というコメントがあります。素晴らしいスタートですね。これはscriptタグではないので、残りはおそらくHTMLで、ここで言っているのは必ずしもサーバーサイドのファイルに置くべきということではなく、おそらくJSファイルに置くべきだということです。なぜならこれはHTMLファイルで、認証の仕組みをHTMLに置くべきではありません。人々が検査して見てしまうからです。でもJSファイルに置けば完全に安全ですよね?
もしここで崩壊すると思うなら、これからどれほど恐ろしいことになるのかまだわかっていません。次に、authenticate user関数があります。この関数は正しいスペルで書かれていて、それが私が言える唯一の褒め言葉です。ここから非常に急激に下り坂になっていきます。
accounts equals API service.SQLは「select * from users」です。はい、このコードは全てのユーザーをデータベースからフェッチして変数として保存します。正直に言うと、私もここや他の場所でこのようなコードを書いたことがあります。そうでないふりはしません。しかし、クライアントサイドでこれを行ったことは一度もありません。なぜなら、それは本当に愚かだからです。
最近行った中で最も近い理にかなった例を挙げると、「one app five Stacks」というプロジェクトに取り組んでいて、同じアプリを5つの異なるスタックで構築しています。そしてもちろんその1つはNextjsのサーバーコンポーネントを使用したTypeScriptです。ここには、getRankingsを呼び出すresultsページがありますが、getAllPokemonは必要ありません。待って、ここでこのようにやっていませんでした。ああそうです、これは全てKVに置きました。
ここでさえ、そんなに悪くはやっていません。私はもっと賢明でした。全てのポケモンを取得していますが、これはキャッシュされたAPI呼び出しから来ています。まず、これはサーバーでのみ実行され、第二に、データベースのテーブルからselect *を実行していません。
ここには、もっと心配すべき悪いことがたくさんあります。例えば、クライアントで直接SQLを呼び出せる場合、誰でもクライアントから直接SQLを呼び出すことができ、このAPIサービスがグローバルであるため(そうでなければここで呼び出すことができません)、ユーザーは要素を検査し、コンソールに移動して「apis service.SQL」と入力し、そこで「delete * from users」を実行でき、データベースが消えてしまいます。
繰り返しますが、これはクライアントで実行されており、彼らのAPIサービスは単にデータベースを直接のトンネルとしてクライアントに公開しているだけです。正気の沙汰ではありません。スクロールを続けると、さらに悪化していきます。
「for i equals z i is less than accounts.length i++」…待って、質問する前に、そして多くの人がすでに質問していることは分かっていますが、awaitはどこにあるのでしょうか?これを呼び出して待っていないのはなぜでしょうか?このコードはほぼ確実にasync/awaitが存在する前に書かれたもので、ここでブロッキングXHRリクエストを行っていたことは間違いありません。
そのため、このコードが戻ってくるのを待つ間、JSスレッドを保持しているのです。これは、forEachの前、おそらくmapの前でもあったため、リストから一度に1つずつ個別の要素を選択する唯一の方法がJavaScriptでこれだったのです。ひどいですね。
しかし、もっと面白いのは、ユーザー名とパスワードが一致するアカウントを探しているだけで、trueを返していることです。理論的には、これが私たちが見た全てのコードです。このAPIサービスがクライアントサイドで公開されているという大きなセキュリティホールがありますが、少なくともこのパスワードが、authenticate userを呼び出す前にハッシュ化された方法で渡されている限り、これらのユーザーのパスワードは全員に公開されていません。ただそのハッシュだけですよね?
よね?
まあ、スクロールすると、フォームから直接取得しているだけですが、まだauthenticate user関数は終わっていません。なぜなら、マグナムオーパス、デラクレーム、美、芸術にまだ到達していないからです。
AIに引き継いでもらえるのが楽しみです。これより悪くなることはないでしょうから。ほぼ確実に…私の言葉につまりながら、最善を尽くしてSteelmanしようと思います。私の推測では、ある時点で左側は「string true」ではなく、「account.is_active」か何かだったのでしょう。
そのため、「if account.is_active equals string true」(ブール値のtrueではなく、文字列の「true」)だったのでしょう。おそらくデータベースから元々取得したものだったので、ここで「if account.is_active equals true」という文字列をチェックしていたのでしょう。そして、おそらくそれをコピーアウトするか、変更を加えて、それが機能したため、そのまま残したのでしょう。
しかし、これを単純化する方法は17通りくらいあります。if文を使わずに、単に「return true equals true」とするか、「not equal true」とするだけでもいいのです。いや…私は一生懸命にこれがどうやって起こり得たのかを考えようとしていますが、苦労しています。なぜこれが起こるのでしょうか?
少なくとも彼らのjQueryのコードはある程度機能します。IDがloginなので、それはフィールドまたはボタンにタグ付けされたloginで、それをクリックすると、usernameはusername値を選択し、passwordはpasswordフィールドの値を選択し、authenticatedはauthenticate user username passwordの結果です。
そして、ここにこのコードの過小評価されているゴートがあります。「if authenticated equals true dollar sign.cookie logged in yes」彼らは即座にクライアントサイドでクッキーを設定して、ログインしていることを知らせています。これは、ここでブロックされているサーバーコードがある場合、クライアントサイドでのみ「logged in yes」をチェックしていることを意味します。
そして、ほぼ即座に期限切れになります。「expires one」は一体何をするのでしょうか?jQueryのexpiresでは、数字は時間や分ではなく日を表します。ありがとう、Claude、それを確認してくれて。私は知りませんでした。なんて愚かなんだ。
もう一歩進んでみましょう。私は…ええと、もうこれ以上一人で苦しむことはできません。ありがとう、AR、カーソルを開いたのでハードロックしてくれて。素晴らしい、私のブラウザは現在完全にフリーズしています。全く死んでいないブラウザですね。
誰かがここでコードを書き出しています。はい、ここにあります。このコメントも大好きです。「私の職場の面接でこれを見せることを提案し、最低要件として少なくとも4つの悪い点を指摘できることにすべきだ」と。実際、それは良い面接の質問だと思います。普通は逆で、本当に良いコードを見せて、「これは何をするのか」と尋ねます。
このコードには、いくつかの深刻なセキュリティの問題がある問題のある認証の実装が見られます。このコードは、フォーム入力からユーザーとパスワードを取得し、ユーザーを認証しようとし、クッキーを設定し、エラーメッセージを表示するログイン機能を実装しています。
主なセキュリティの脆弱性には、平文のパスワード、SQLインジェクションのリスク、安全でない認証、簡単に変更可能な「logged in equals yes」を使用する弱いセッション管理、奇妙で冗長なロジック、コードの組織化の問題などが含まれます。ありがとう、Claude、とても役立ちます。
ほとんどの人は恐らくここで、誰かがジョークとしてこれを作ったのだろう、これは単に人々を怒らせるために作られた偽のコードだろうと考えているでしょう。しかし違います。これは実際にインターネットアプリで使用されていたのです。これは誤植ではなく、internetという意味です。つまり、企業のローカルネットワークだということです。
おそらく、この種のコードベースで恐ろしいものを見てきました。このようなコードベースは、オフィスでイーサネットに接続しない限りページにアクセスできないため、外部に公開されていません。そのため、これらのセキュリティについてはあまり考えない傾向があります。
元の投稿者は彼らのコメントを削除しましたが、以下のようなコメントでした:「これは現在も実際に使用されています。最悪なのは、このインターネットが公開されているということです。ああ、神よ、これは従来のインターネットではなく、ローカルだけでもなく、ネットワークにログインしているわけでもありません。企業のウェブサイトから公開的にアクセスできます。ああ、なんてことだ。」
また、これはCapital Oneとは関係ないと指摘されています。彼らは金融フォームで何かについて不満を言っていたため、アカウント名がCapital One throwawayになっているのです。ただし、これが金融企業だとしても驚きませんが。
明らかに、このユーザーは他の同様に恐ろしいコードもあちこちに投稿していました。セキュリティのないAPI、JavaScriptのfetchリクエストでSQLを実行する、HTMLを読み込む、安全な接続を確立する…このコードベースでセキュリティに最も近いものは、「establishing secure connection」という言葉を使用していることです。
boldとsetTimeoutで「loading…processing security protocol」2000ミリ秒、そして3秒後に「secure connection established」と表示するだけの嘘です。また、これら2つは矛盾しています。これらは2つの3秒のタイムアウトで、競合状態になります。
「API service.sendRequest(“select * from analytics where user_id = ” + user)」…これがサーバーサイドのコードだったとしても、これは悪いです。ああ、まったく。正直に言うと、ここで最も信じられるのは、ハードコードされたサーバー名です。これは、このコードが実際に存在し、内部ツールとして使用されていたことを示唆しています。
よし、わかったと思います。これはデータアナリストかIT担当者で、彼らが行うことを公開するためのコードを書かざるを得なかったのだと思います。ここでアナリティクスから選択しているので、データ担当者だと思います。
これは、全てのデータとIT担当者が行うことだと推測します。これは、私がいつも参照するXKCDの一つです。「町のすぐ外なので、15分で着くはずです。実際には6日くらいかかりそうです。いや待って、30秒です。」Windowsのファイルコピーダイアログの作者が友人を訪ねるという内容です。
これは、全てのデータアナリストとIT担当者との私の経験でもあります。彼らは見積もりが常に賢明であることに慣れているからです。だから、彼らは私たちにも同じことをしているのです。
これがデータ担当者で、彼らのツールが読み込み状態について嘘をつくことに慣れているなら、彼らが私たちに読み込み状態について嘘をついていることに驚くべきではありません。そして、同じsetTimeoutを3回呼び出していることは、それらが矛盾するということです。これらは全て同期的に発生するため、これが呼び出され、次にこれ、次にこれ、次にこれというように進みます。
彼らは同期と非同期の概念を理解していないようです。なぜなら、これらは全て競合することになるからです。これは明らかに、職業としてJavaScriptを書いている人ではありません。これは他のことをする人で、仕事をするためにJavaScriptを急いで書こうとしている人です。それでも絶対に恐ろしいですが。
ワオ、私はこれが出たときにTwitchで仕事を始めたばかりでした。では、この更新されたバージョンを見てみましょう。これにはログイン構文エラーがあります。面白いことに、これにはlogin failedの部分がありますが…待って、スペースさえありません。これが何度も変換されているのは本当に興味深いです。
login failはここではスペースがありませんが、ここにはあります。ここで何が起こっているのでしょうか?これは旅です。まあ、確実に言えることは、私たちは開発者よりもこのコードについて多くの考察をしてきたということですが、なんてことだ。
私の理論では、これがイタリアの「shitty programmer」というFacebookページに追加されたとき、英語を母語としない人々にもコードをより読みやすくし、何が起こっているのかを明確にするために、ここにlogin failedを追加したのかもしれません。それが私に想像できる唯一のことです。
そして「dollar sign.show」は…ちょっと確認させてください。「dollar sign element.show」は何をするのでしょうか?これはCSSをnoneから元の値に変更すると思いますが…はい、その通りです。引数を渡せるとは思っていませんでした。ああ、表示に要する時間の引数を渡すことができるんですね。jQueryがどれほど素晴らしいかを忘れていました。それはとても便利な機能です。
login failedは全く渡せるものではありません。それを確認したかったんです。はい、showに渡せるのは数字以外にはありません。上でlogin failedを数字として定義していない限り…
authenticate user us passwordは全て同じです。「select * from users return true if tr is true return false login click function dollar sign username username password password」はい、唯一の変更点はこの行だけです。IDセレクターを削除したのは奇妙です。これでは機能しません。
error messageをIDやクラス名なしで選択することはできないからです。このような形で、前にドットかハッシュが必要です。元のバージョンでは、このコードは機能します。うまく機能するわけではありませんし、使うべきではありませんが、技術的には機能します。しかし、この変更されたバージョンは機能しません。
そして、これはツイートに載っていたバージョンですね。はい、わかりました。このバージョンはどれくらい違うのでしょうか?ほとんど同じだと思いますが、確認したいと思います。はい、その通りです。では、なぜこの行だけが何度も変更されているのでしょうか?なぜ実際のコードの最後の行がこのコードの全てのバージョンで変更されているのでしょうか?ここで何が起こったのでしょうか?
Googleでこの正確な文字列を検索してみましょう。ワオ、私が投稿したので誰かが再投稿し、これが元々来たところだと知らずにプログラミングホラーに再度投稿しています。ああ、神よ、このバージョンは引用符を間違えていますね。はい、それは異なる引用符を使用しています。
よし、新しい理論が思い浮かびました。私はこれを理解したと思います。これは、粗悪なテキストのOCRコピー貼り付けを使用してコピーされたのだと思います。例えば、ここでMac OSのプレビューを使用して、このようにテキストを選択できます。
私の推測では、誰かがそれを素早く取得するためにそれを行い、見つけたエラーを修正し、最後にその粗悪なlogin failedの部分を追加したのでしょう。そして、別の誰かが画像の2番目の変更のためにOCRコピーを行ったのでしょう。なぜなら、これは色の解像度がはるかに高いからです。
ああ、待って、私の理論を確認しました。見てください、文字のリガチャーとラッピングのエンコードがどれほど貧弱かを見てください。これは何か奇妙なAIです。これはOCRコピーを介して作られ、これはAI生成のアップスケーラーで作られました。
明らかに、W2xはそのような空白を追加することで知られているようです。時々、AI生成のアップスケーラーは、OCRコピーに基づいてそのようなことをします。はい、ここで奇妙さが見えます。teのここの丸みの奇妙さを見てください。これは間違いなくAIによる画像のアップスケーリングからのものです。
なぜなら、これは壁紙用だったことを覚えておいてください。誰かがこの古いスクリーンショットを持っていて、隅や上部から要素を削除し、「これを壁紙にしたいけど、解像度が低すぎる」と思い、このwfu 2xアップスケーラーを使用してアップスケールしたのでしょう。それが下部のスペースも追加したのでしょう。
そして、それを使用して、何も考えませんでした。コードがすでにひどかったので、彼らはコードを知らなかったか、悪いコードのためのものにする意図があったのでしょう。私はその理論で行きます。私たちはそれを解明したと思います。
なんという旅でしょう。この恐ろしいコードから、それが存在する更に恐ろしい理由、そして最も恐ろしい理由である、それが壁紙になったことまで。私たちは全てを解明したと思います。そして最後に、まだAIを非難することができます。
次回まで、さようならナード達。
コメント