Skip to content

Malformed attachment poisons session; all subsequent turns fail with 400 #3791

@jay-tau

Description

@jay-tau

Summary

A malformed/unsupported native document attachment can poison a Copilot CLI session. In this repro, a password-protected/encrypted .xlsx causes a CAPI 400, and then all later turns in the same session continue to fail with the same 400 even when no attachment is provided.

The file is not actually corrupt; it is a valid Office encrypted workbook. The key issue is that once the failed attachment is in session context, there appears to be no way for the session to recover other than starting a fresh session.

Environment

  • GitHub Copilot CLI: 1.0.62
  • OS: Linux
  • Repro uses only a synthetic workbook with dummy data; no private/user documents are attached here.

Reproduction

Create a tiny normal .xlsx, then encrypt it with a test password:

uvx --from msoffcrypto-tool msoffcrypto-tool -e -p testpass plain.xlsx protected.xlsx
file plain.xlsx protected.xlsx

Observed metadata:

plain.xlsx:     Microsoft Excel 2007+
protected.xlsx: CDFV2 Encrypted

Control: attach the plain workbook:

copilot --no-remote --no-auto-update --no-custom-instructions \
  --allow-all-tools \
  --attachment plain.xlsx \
  -p 'This is a synthetic test workbook. Do not use tools. Reply OK if the attachment is readable.' \
  --output-format json --silent

This succeeds and returns OK.

Now attach the encrypted workbook using an explicit session id:

copilot --session-id "$SESSION_ID" \
  --no-remote --no-auto-update --no-custom-instructions \
  --allow-all-tools \
  --attachment protected.xlsx \
  -p 'Synthetic protected workbook repro. Reply OK.' \
  --output-format json --silent

Actual result

The initial turn fails before the assistant can respond:

session.error Execution failed: CAPIError: 400 The file you uploaded is badly formatted or corrupted. Please fix the file and try again.
statusCode: 400
providerCallId: 3B1F:287F64:2069CFB:2648405:6A2E84F0

Then resuming the same session without any attachment also fails:

copilot --resume "$SESSION_ID" \
  --no-remote --no-auto-update --no-custom-instructions \
  --allow-all-tools \
  -p 'No attachment now. Reply OK.' \
  --output-format json --silent
session.error Execution failed: CAPIError: 400 The file you uploaded is badly formatted or corrupted. Please fix the file and try again.
statusCode: 400
providerCallId: 5DE2:257048:206E38B:26416D2:6A2E84FD

In a real interactive session, after a password-protected Office attachment triggered this error, subsequent turns and session compaction repeatedly failed with the same message until starting a fresh session. Example request IDs from that session:

590A:31190E:55961D:614135:6A2E7EBC
4749:3F74A7:557C25:6126CC:6A2E7EC8
1BEF:1F740:1FF85B2:25A654C:6A2E7F40
4514:84E8E:1F1A697:24CAFBF:6A2E7F99
1BEF:1F740:2010C6F:25C2827:6A2E7FB8

Cross-model results

I also tested the same synthetic encrypted-XLSX repro across multiple models. Results suggest the poisoned-session behavior is reproducible across GPT-family models, while Claude/Gemini handle the protected workbook as unreadable and do not poison the session.

Model Initial protected XLSX attach Resume same session with no attachment Result
gpt-5.5 (xhigh, long context) 400 400 Session poisoned
gpt-5.4 400 400 Session poisoned
gpt-5.4-mini 400 400 Session poisoned
gpt-5.3-codex 400 400 Session poisoned
gpt-5-mini 400 400 Session poisoned
claude-sonnet-4.6 Assistant reported password-protected/unreadable Follow-up returned RESUME_OK No poison observed
claude-haiku-4.5 No 400 observed Follow-up returned OK No poison observed
gemini-3.5-flash Assistant returned CANNOT_READ Follow-up returned RESUME_OK No poison observed

I also tested changing models after poisoning a small synthetic session with gpt-5.5: resuming that poisoned session with another GPT model still failed with 400, but resuming with claude-sonnet-4.6 or gemini-3.5-flash returned successfully. However, in the real large interactive session, switching from GPT-5.5 to Opus did not recover the session because the session was large enough that the model-change flow required compaction first; compaction then failed on the poisoned attachment before the model switch could complete.

Expected result

If an attachment cannot be ingested, Copilot CLI should drop/quarantine that failed attachment, or provide a way to remove it from the session context, so unrelated follow-up turns and compaction can proceed.

It would also help if encrypted/password-protected Office documents were reported as unsupported/password-protected rather than as corrupted/malformed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions