Skip to content

Commit 23dedaf

Browse files
takemi-ohamaclaude
andcommitted
fix(env): PR #22 round1 codex/gemini 指摘対応
- bundle.py: manifest version チェックを厳密一致 (!=) に変更し、 0 や負数の未知スキーマを拒否 (codex major 指摘) - cli.py: import --identity の help を "(all existing ones)" に修正 (codex minor 指摘、resolve_identity_specs は全鍵を返す) - io_import.py: --identity と --passphrase-* の同時指定を _validate_options で拒否 (gemini major 指摘) - テスト追加: version=0/-1 の拒否、identity+passphrase 排他チェック Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b1e85d6 commit 23dedaf

5 files changed

Lines changed: 26 additions & 5 deletions

File tree

lib/devbase/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ def _add_env_parser(subparsers):
179179
metavar='FILE', dest='identities',
180180
help=("age / OpenSSH private key file (repeatable). "
181181
"Default: ~/.ssh/id_ed25519, then ~/.ssh/id_rsa "
182-
"(first existing one)"))
182+
"(all existing ones)"))
183183
env_import.add_argument('--passphrase-env', metavar='VAR', default=None,
184184
help='Read passphrase from environment variable VAR')
185185
env_import.add_argument('--passphrase-stdin', action='store_true',

lib/devbase/env/bundle.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,10 @@ def _validate_manifest(manifest: Dict, members: Dict[str, bytes]) -> None:
164164
version = manifest.get('version')
165165
if not isinstance(version, int):
166166
raise BundleError("manifest.version が不正です")
167-
if version > SUPPORTED_MANIFEST_VERSION:
167+
if version != SUPPORTED_MANIFEST_VERSION:
168168
raise BundleError(
169169
f"manifest.version={version} はこの devbase ではサポートされていません "
170-
f"(対応最大={SUPPORTED_MANIFEST_VERSION})。devbase 本体を更新してください"
170+
f"(対応={SUPPORTED_MANIFEST_VERSION})。devbase 本体を更新してください"
171171
)
172172

173173
files = manifest.get('files') or []

lib/devbase/env/io_import.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ def _validate_options(opts: ImportOptions) -> None:
8585
)
8686
if opts.passphrase_env and opts.passphrase_stdin:
8787
raise ImportError("--passphrase-env と --passphrase-stdin は併用できません")
88+
if opts.identities and (opts.passphrase_env or opts.passphrase_stdin):
89+
raise ImportError(
90+
"--identity と --passphrase-env/--passphrase-stdin は併用できません"
91+
)
8892

8993

9094
def _decrypt_if_needed(blob: bytes, opts: ImportOptions) -> bytes:

tests/cli/test_env_import.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,18 @@ def test_import_rejects_both_passphrase_env_and_stdin(dest_root):
206206
source='/dev/null', passphrase_env='X', passphrase_stdin=True))
207207

208208

209+
def test_import_rejects_identity_with_passphrase(dest_root):
210+
"""--identity と --passphrase-env/--passphrase-stdin の同時指定は拒否される"""
211+
with pytest.raises(ImportBundleError, match="--identity と --passphrase"):
212+
import_bundle(dest_root, ImportOptions(
213+
source='/dev/null', identities=['/tmp/fake.key'],
214+
passphrase_env='X'))
215+
with pytest.raises(ImportBundleError, match="--identity と --passphrase"):
216+
import_bundle(dest_root, ImportOptions(
217+
source='/tmp/dummy', identities=['/tmp/fake.key'],
218+
passphrase_stdin=True))
219+
220+
209221
def test_read_passphrase_uses_getpass_on_tty(monkeypatch):
210222
"""tty 入力時は getpass.getpass を使い stdin.readline は呼ばない (エコー抑止)"""
211223
fake_stdin = io.StringIO("should-not-be-read\n")

tests/env/test_bundle.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ def test_unpack_rejects_corrupted_sha256():
4949
bundle.unpack(out.getvalue())
5050

5151

52-
def test_unpack_rejects_unknown_version():
52+
@pytest.mark.parametrize("bad_version", [
53+
bundle.SUPPORTED_MANIFEST_VERSION + 1,
54+
0,
55+
-1,
56+
])
57+
def test_unpack_rejects_unknown_version(bad_version):
5358
entries = [_entry("env/global.env", b"FOO=bar\n")]
5459
blob = bundle.pack(entries)
5560

@@ -62,7 +67,7 @@ def test_unpack_rejects_unknown_version():
6267
data = tin.extractfile(info).read()
6368
if info.name == bundle.MANIFEST_NAME:
6469
m = yaml.safe_load(data)
65-
m["version"] = bundle.SUPPORTED_MANIFEST_VERSION + 1
70+
m["version"] = bad_version
6671
data = yaml.safe_dump(m).encode("utf-8")
6772
info.size = len(data)
6873
tout.addfile(info, io.BytesIO(data))

0 commit comments

Comments
 (0)