OpenHands Headless Modeの実装を読む

昨今、巷ではClineDevinによるAIコーディングが話題です。特にDevinのような「タスクを渡したら、完了まで自律的に思考と行動を繰り返すエージェント型ソフトウェア」には、面倒だけど微妙に自動化しきれない作業を巻き取ってくれる可能性を秘めていると期待しています。例えば、machine-readableでない文書を定期的に監視して変更を実装に反映する、などです*1

そもそも、どのようにしてAIに自律的に思考と行動を繰り返させているのでしょうか?AIの最新情報には疎いので、実装イメージがパッと思い浮かびません。どのようなアーキテクチャになっているのか非常に興味が湧いてきました。

Devinは商用プロダクトなのでコードベースは公開されていませんが、類似のオープンソース実装であるOpenHandsであればコードが読めます。本記事はもっとも仕組みが単純そうなHeadless Modeの実装を読んでみたメモです。

*1:例えば、メンテしているTFLintのAWS rulesetでは定期的に公式ドキュメントを参照して有効な値を実装に反映する、みたいな不毛な作業があります... https://github.com/terraform-linters/tflint-ruleset-aws/pull/803

続きを読む

criu restoreを非特権コンテナから呼ぶことはできるか

CRIUによるプロセスのリストアには複数のcapabilityが必要であり、コンテナ内部で行うためには--privileged相当で起動された特権コンテナでなければいけません。例えば、TCP connection repairCAP_NET_ADMINが必要なのは明らかですが、もっと単純なプロセスであれば非特権コンテナでもリストアできるのでは...?と考えたのが事の始まりです。

続きを読む

sigstoreのKeyless Signingでは何を検証しているのか

最近、個人的にsigstoreのKeyless Signingがアツいです。以下のブログを読みました。

これらの記事は主にコンテナイメージの署名について解説しているのですが、sigstoreはバイナリの署名にも使えます。以前から、複数メンテナ体制で秘密鍵をどう共有しよう?とか、公開鍵の安全な配布方法って無くない?と考えていたので、渡りに船です。

早速、採用に向けて色々調べていたのですが、署名した人をどう確認しているのか、改ざんされていないことをどう保証しているのかがわからなかったので、Keyless Signingでは何を検証する必要があるのかを調べました。

全然わからない状態から調べているので、間違ったことを書いてるかもしれません。何か間違いを見つけたらTwitterとかで教えて下さい。

続きを読む

コンテナはなぜ安全(または安全でない)なのか

CVE-2019-5736を覚えていますか?今年の2月に見つかったrunc(Dockerがデフォルトで利用しているコンテナのランタイム)の脆弱性で、ホストのruncバイナリを好き勝手にコンテナ内部から書き換えることができるというものです。

脆弱性の仕組みに興味があったので調べたところ、コンテナを攻撃する方法というのは他にもいろいろあって、runcは頑張ってそれを塞いでいるようです。これまとめると面白いかも、と思ったので以下のようなおもちゃを作りました。

Drofuneは簡単なコンテナランタイムです。drofune runとかdrofune execなどでコンテナを起動したり、入ったりすることができます、といえば想像がつくでしょうか。

これだけでは何も面白くないので、Drofuneはわざと安全でない実装になっています。なので、今回発見されたCVE-2019-5736を利用した攻撃も成立します。このプロジェクトは攻撃コードがどのように動き、どのように防げるのかを試すことが目的です。

続きを読む

Rubyのprivateを考える

RuboCopのIssueを眺めていると、いろいろな人のRubyの考え方に触れることができて面白い。例えば、多くのRubyistにとってprivateなメソッドを宣言したいときには、以下のような書き方をすると思う。

class Cat
  def meow
    puts "Meow!"
  end

  private

  def bowwow
    puts "Bowwow!"
  end

  def cock_a_doodle_doo
    puts "cock-a-doodle-doo"
  end
end

privateの後にインデントするとかしないとか、微妙な差異こそあれど、大体こんな感じ。でも、これをよくないと考える人もいる。ではどうするのかというと、以下のようにインラインでアクセス修飾子を書くべきだという主張。

class Cat
  def meow
    puts "Meow!"
  end

  private def bowwow
    puts "Bowwow!"
  end

  private def cock_a_doodle_doo
    puts "cock-a-doodle-doo"
  end
end

以下はこのスタイルを強制することができるCopを追加するプルリクエスト。RuboCop v0.57.0 以上を使っているならば、EnforcedStyleinlineにすれば、すぐに試すことができる(ただ、v0.57.2 時点でいくつかの問題が報告されているので、有効にして運用するのはちょっとオススメしない...)

続きを読む

gomockでaws-sdk-goをモック/スタブする

普段、Rubyを書いていると、Goでaws-sdkを扱う際にAPIの呼び出しをモック/スタブするのが意外と大変で苦労する。よくGoのテストのプラクティスとして、スタブしたい関数をグローバル変数に入れておいて、テスト時にすり替えるというのがあるが、もうちょっとなんとかならないかと思ったりする。

以前、gomockを使った、いい感じのaws-sdk-goのモック/スタブ方法を見かけて、それ以来、実践しているのだけれど、残念なことにその元記事が消えてしまった(たぶん)。せっかくなので、この方法論をまとめておくことにした。

続きを読む

RuboCopの Rails/InverseOf について調べた

最近、RuboCopへのパッチを投げるようにしているのですが、なんか良さそうなバグは無いかなとissueを漁っていたところ、こんなissueを見つけました。

このissue自体は単なるfalse positiveなので、まぁ対応すれば良いのですが... こっちがその問題のCopが追加されたプルリクエスト。

このCopが教えてくれることは、状況によっては :inverse_of を明示的に指定しないと、意図した挙動をしないことがあるので、その場合にはちゃんと :inverse_of を書きなさいね、ということです。ただ、1個目のissueのコメントで「Railsガイドには :through とか :polymorphic を指定していると、:inverse_of は効かないって書いてあるけど、それでも指定しないとダメなの?」と言っている人もいます。

:inverse_of については、Railsのバージョンアップによってデフォルトで指定しなくても動くようになった経緯などもあって、いつ指定すべきで、いつ指定しなくてもいいのか、いまいち理解が曖昧だったので、ちょっと調べることにしました。

続きを読む