<a id="ch-10"></a>

## Chapter 10 — One flipped bit and one added line

<!-- open-cyber-academy:lesson-figures:start ch-10 -->
### Lesson map

Lesson 10. Map, example, EX056.

```mermaid
flowchart TD
  M["model.bin index 5000, XOR 1"] --> X["Full digest changes"]
  C["config.yaml gains one line"] --> X
  T["tokenizer bytes stay put"] --> K["That line prints OK"]
```

Either change is enough. The unchanged file is the one that passes.

### Logical drawing

```text
model.bin index 5000 ^= 1
config.yaml gains trust_remote_code: true
tokenizer.json bytes unchanged
```
<!-- open-cyber-academy:lesson-figures:end ch-10 -->

### Learning outcomes

After this chapter, you should be able to:

1. Point at index 5000 and the XOR that flips one bit.
2. Name the extra config line that replaces the two-line file.
3. Say why the tokenizer line is the only OK.

### 10.1 The manifest is computed first. The received bytes are altered second.

The model artefact is `bytes(range(256)) * 40`, which is 10,240 bytes. The code copies it into a `bytearray`, does `tampered[5000] ^= 1`, and stores the result back. Index 5000 is inside the file. XOR 1 flips the lowest bit of that byte and leaves every other byte alone. SHA-256 of the result does not equal the stored digest, so the status word is MISMATCH. One bit is enough.

The config starts as `layers: 4\nheads: 8\n`. The received value replaces it with those same two lines plus `trust_remote_code: true\n`. The extra line changes the bytes, so the config digest fails too. The tokenizer value stays `b'{"vocab": ["a", "b"]}'`. Its recomputed digest equals the manifest, so that line is OK.

The JSON prefixes were printed from the clean manifest, before these assignments. A reader who looks only at `e96760a87768717b` is looking at the original model digest's prefix. The status line underneath is the check of the altered bytes. Familiarity of the prefix does not cancel the MISMATCH.

| File | What changed | Status word |
|---|---|---|
| model.bin | One bit at index 5000 | MISMATCH |
| config.yaml | One added line | MISMATCH |
| tokenizer.json | Nothing | OK |

### 10.2 Worked example

| Proposal | Decision |
|---|---|
| "Reload the model file because one bit moved." | Keep; do not use the mismatched bytes |
| "The prefix still looks right, so accept it." | Refuse |
| "The tokenizer line can stay." | Keep; those bytes were not altered |
| "A real downloaded weight file would behave like these 10,240 bytes." | Refuse; this file is synthetic |

> **Synthetic case.** No production model is opened. The lab builds the bytes itself.

### Errors and limits

Calling the model safe because its printed prefix looks unchanged ignores the line that says MISMATCH.

### Apply

- **EX056 — Two changes.** What was done to model.bin and to config.yaml, and why is tokenizer.json the OK line? *Rubric:* 3 = index 5000 XOR 1, plus the added trust_remote_code line; tokenizer bytes are unchanged so the full digests match; a familiar prefix is not a pass;; 2 = both changes and the OK reason;; 1 = one change;; 0 = accepts the model file.

<!-- open-cyber-academy:chapter-navigation:start ch-10 -->
### Continue studying — lesson 10 (chapter 10 of 20)

[← Chapter 09](#ch-09) · [Course chapter index](../SUBJECTS.md) · [Chapter 11 →](#ch-11)

Continue to the next authored lesson.
<!-- open-cyber-academy:chapter-navigation:end -->

## Worked answers

<a id="answer-ex056"></a>
**EX056.** model.bin is 10,240 synthetic bytes, and index 5000 is XOR 1, so one bit changes and the full digest mismatches. config.yaml gains the line trust_remote_code: true and also mismatches. tokenizer.json is unchanged, so it prints OK. The printed prefix of the clean model digest does not cancel the MISMATCH.
