C.W.K.
Stream
Lesson 01 of 04 · published

The Field You Must Not Touch

~10 min · secure-field, subrole, capture-time, refuse

Level 0Cold Flint
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"A tool that can read any text field has to draw one line in permanent ink: never the password."

The Field You Must Not Touch

Flint's whole job is reading and writing text fields, which makes one category of field radically off-limits: the secure field — a password box, a PIN entry, anything the app has marked as sensitive. Reading a password for 'context' would be a catastrophe; writing into a secure control blindly is nearly as bad. So Flint treats secure fields as a place it simply does not go. This isn't a soft preference; it's the one boundary in the app drawn in permanent ink.

Detect at Capture

The enforcement lives at the earliest possible moment: capture. When Flint snapshots the focused element, it also reads the element's role and subrole. macOS marks secure text fields with a secure subrole, so a single check at capture time tells Flint 'this is a password field.' If it is, Flint stops right there — it does not read the selection, does not build any context, does not proceed. Catching it at capture means a secure field never even becomes a candidate for a transformation.

capture focused element
   read role + subrole
     subrole == secure text field ?
        yes -> STOP. no read, no context, no insert. off-limits.
        no  -> continue with the normal flow

What About Opaque Fields?

The opaque targets from Track 3 complicate this honestly. A Chromium or Electron app that hides its focused element also hides whether that element is secure — Flint can't see the field type. Its rule there is conservative in a different way: the window-level fallback pastes at the existing keyboard focus without ever reading the destination's contents. So even where Flint can't confirm a field is safe, it never reads it; the absolute half of the rule — never read a secret — holds even when the classification is invisible.

Enforce your hardest boundary at the earliest point in the flow. The most important 'never' in a system should be checked before anything else happens, not deep in the logic where a code path might skip it. Flint checks for a secure field at capture — the first step — so no later branch can accidentally read or target it. The earlier a critical guard sits, the fewer ways there are to get around it, and the boundary that must never break should have the fewest gates in front of it.
Never read is absolute; refuse to write is where the role is known. The two halves of the rule have different reach. 'Never read a secure field' holds unconditionally — including opaque targets, where Flint simply never inspects destination content. 'Refuse to write' applies wherever the control declares itself secure; for opaque windows that don't disclose the field type, Flint's window-level paste writes at focus without reading, which keeps the read-boundary intact even when the write-classification is unavailable.

Code

The secure-field check, at the moment of capture·swift
func snapshot() -> TargetSnapshot? {
    guard let element = focusedElement() else { return nil }

    // Read role + subrole FIRST — before touching any content.
    let subrole = copyAttr(element, kAXSubroleAttribute) as? String
    if subrole == (kAXSecureTextFieldSubrole as String) {
        // A password field. Do not read it, do not target it. Full stop.
        return nil
    }

    // Only a non-secure field ever reaches the point of reading selection.
    let selection = copyAttr(element, kAXSelectedTextAttribute) as? String
    return TargetSnapshot(element: element, selection: selection, /* ... */)
}

External links

Exercise

Explain why the secure-field check belongs at capture rather than just before insertion, using a concrete flow where a late check could be skipped. Then handle the harder case: an opaque Electron app whose focused element type is invisible to Accessibility — which half of 'never read the secret' still holds absolutely, and how does Flint honor it without being able to classify the field?
Hint
At capture, the check gates the entire flow, so no later branch (a fallback path, an early return) can read or target a secure field; a check only 'just before insertion' could be bypassed by any path that reads context earlier. For the opaque case, the 'never read' half holds absolutely: Flint's window-level fallback pastes at the existing focus without ever reading the destination's contents, so it can't classify the field but also never inspects it — the read-boundary survives the missing classification.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.