Skip to content

bug: never unpickle agent-writable files when loading experiment results (sfind-454ac387) - #66

Open
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/sfind-454ac387-safe-result-loading
Open

devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/sfind-454ac387-safe-result-loading

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Resumo

Corrige o finding sfind-454ac387 (high): ao carregar resultados, o AgentLab fazia pickle.load em qualquer exp_args.pkl encontrado por glob("**/exp_args.pkl") dentro do diretório do estudo — inclusive em <study_dir>/shared_code, que é o diretório de trabalho do sandbox de código do GAIA (gravável pelo agente). Um agente induzido por prompt injection podia gravar shared_code/x/exp_args.pkl e executar código no host quando Study.run chamava get_results ao fim de cada trial.

Duas camadas:

  1. Descoberta (yield_all_exp_results em loop.py): o glob recursivo foi trocado por _find_exp_dirs, que usa os.walk(followlinks=False), nunca entra em CODE_SANDBOX_DIR_NAME ("shared_code") e não desce dentro de um diretório de experimento (o AgentLab nunca aninha experimentos; isso cobre o symlink exp_dir/code -> shared_code). Ordem agora determinística (ordenada). gaia.init_code_sandbox passa a usar a mesma constante.
  2. Desserialização (ExpResult.exp_args, get_step_info, goal_object.pkl.gz): novo agentlab.experiments.safe_pickle.load, um pickle.Unpickler com find_class restrito:
    • só classes (nunca funções como exec, os.system, Path.write_text), exceto helpers de reconstrução (copyreg._reconstructor, numpy..._reconstruct/scalar/_frombuffer, _codecs.encode);
    • qualquer classe de agentlab, browsergym, bgym + raízes extras em AGENTLAB_TRUSTED_PICKLE_MODULES (separadas por vírgula, p/ agentes em pacotes próprios);
    • subclasses dessas classes definidas em módulos já importados no processo (ex.: AgentArgs/BaseModelArgs customizados no script de lançamento ou em testes) — nada é importado para resolvê-las;
    • typing.Any (metadados de DictConfig do OmegaConf/Hydra usados pelo GAIA);
    • de tapeagents/pydantic/omegaconf/openai/anthropic apenas dataclasses, enums, modelos pydantic e nós omegaconf (evita gadgets como ContainerExecutor);
    • tipos de valor de stdlib/numpy (ndarray, dtypes, escalares; numpy.memmap bloqueado) e PIL.Image.Image.
    • Global fora da lista → UnsafePickleError (subclasse de UnpicklingError) com mensagem indicando a env var.

Compatibilidade: os pickles de tests/data/test_study (era BrowserGym) carregam normalmente. Resultados que referenciem classes de pacotes de terceiros fora da lista passam a exigir AGENTLAB_TRUSTED_PICKLE_MODULES=<pacote>. study.pkl.gz (Study.load) continua com pickle.load: fica na raiz do estudo, fora do alcance do sandbox, e contém DataFrames pandas — migrar para formato só-dados fica como follow-up.

Como testar

source ~/venvs/agentlab/bin/activate
pytest -q tests/experiments/test_safe_result_loading.py tests/analyze/test_inspect_results.py \
  "tests/experiments/test_launch_exp.py::test_relaunch_study" tests/experiments/test_study.py tests/experiments/test_args.py
# 15 passed, 1 skipped

test_safe_result_loading.py cobre: arquivos plantados em shared_code/x, shared_code/a/b, via symlink exp_dir/code e aninhados num experimento não são listados por yield_all_exp_results/load_result_df/Study.load_exp_args_list; diretórios symlinkados não são seguidos; payloads em exp_args.pkl, step_0.pkl.gz e goal_object.pkl.gz levantam UnsafePickleError sem criar o marker; round-trip de StepInfo real (numpy, Discussion, AgentInfo, StepTimestamps) e a env var.

Reprodução do cenário do finding (estudo de teste + shared_code/x/exp_args.pkl que grava um marker), antes/depois:

[before] load_result_df: raised AttributeError: 'NoneType' object has no attribute 'exp_dir'
[before] marker created (code ran on host) = True
[after]  load_result_df: ok; planted listed=False
[after]  Study.load+load_exp_args_list: ok; planted listed=False
[after]  marker created (code ran on host) = False

Sem mudança de contrato de API pública além da nova env var AGENTLAB_TRUSTED_PICKLE_MODULES e da exceção UnsafePickleError. Testes de ponta a ponta com MiniWoB não foram rodados (servidor MiniWoB não disponível offline).

Devin-Org: engineering

Link to Devin session: https://devin-gtm.devinenterprise.com/sessions/252d9207aa9545648a72ae60d8adfce9
Open in Devin Desktop: https://devin-gtm.devinenterprise.com/desktop/session/252d9207aa9545648a72ae60d8adfce9?variant=devin


Devin Review

Status Commit
⚪ Not started —

Run Devin Review

Enable auto-review to review your pull requests automatically.

Devin Review (Staging)


Devin Review

…lts (sfind-454ac387)

- yield_all_exp_results walks with os.walk(followlinks=False), skips the
  shared_code sandbox and does not descend into experiment directories.
- ExpResult loads exp_args.pkl / step_N.pkl.gz / goal_object.pkl.gz with a
  restricted unpickler (class allowlist, AGENTLAB_TRUSTED_PICKLE_MODULES).
@devin-ai-integration

Copy link
Copy Markdown
Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants