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.
Summary
A malformed/unsupported native document attachment can poison a Copilot CLI session. In this repro, a password-protected/encrypted
.xlsxcauses 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
1.0.62Reproduction
Create a tiny normal
.xlsx, then encrypt it with a test password:Observed metadata:
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 --silentThis succeeds and returns
OK.Now attach the encrypted workbook using an explicit session id:
Actual result
The initial turn fails before the assistant can respond:
Then resuming the same session without any attachment also fails:
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:
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.
gpt-5.5(xhigh, long context)gpt-5.4gpt-5.4-minigpt-5.3-codexgpt-5-miniclaude-sonnet-4.6RESUME_OKclaude-haiku-4.5gemini-3.5-flashCANNOT_READRESUME_OKI 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 withclaude-sonnet-4.6orgemini-3.5-flashreturned 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.