skip to content

What does TAC_PLUS_UNENCRYPTED_FLAG signal in a TACACS+ header, and what does RFC 8907 require of each peer?

level: middleimportance: should knowfreq 36%

answer

  1. one bit says the body is unmasked
  2. SHOULD be clear, MUST NOT in production
  3. the receiver drops such a request
  4. a mismatch closes the TCP session
  5. treated as FAIL, never ERROR

basics

~20 s

TAC_PLUS_UNENCRYPTED_FLAG := 0x01 in the TACACS+ header says the sender left the body unobfuscated. RFC 8907 says it SHOULD be clear in all deployments and MUST NOT be used in production, and a receiver MUST drop such a request.

solid answer

~50 s

The flag is one bit in the header's `flags` byte, and it states a fact about the packet: set means the body was not masked with the `pseudo_pad`. The rules sit at different strengths and should not be flattened together. Section 4.1 says the flag **SHOULD** be clear in all deployments and **MUST NOT** be used in production. Section 4.5 says a request carrying it **MUST** be dropped. Section 10.5.2 adds that servers **MUST** reject connections with it set, that clients — in TACACS+ the client is the network device — **MUST NOT** set it and **MUST** require explicit configuration before clear text can be enabled at all, and that a client seeing a mismatch between its configured expectation and the received flag **MUST** close the TCP session and treat the response as a FAIL.

code

pseudocode · 10 lines
pseudocode
on receive(packet):
    if packet.header.flags AND TAC_PLUS_UNENCRYPTED_FLAG:
        if this_peer is a server:
            reject the connection            # Section 10.5.2
            return
        if this_peer expected obfuscation:   # client-side mismatch
            close the TCP session            # Section 10.5.2
            treat the response as FAIL       # not ERROR
            return
    body = mask(packet.body, pseudo_pad(...))

go deeper

for a junior

Remember the direction: the flag set means the body was left unmasked. It is a report about the packet, not a switch that turns protection on.

for a middle

Separate the SHOULD from the MUSTs and say what each side does — the server rejects the connection, and the device that expected obfuscation closes the session and calls it a FAIL.

for a senior

Explain why FAIL rather than ERROR is the required handling, and what an attacker gains if an implementation gets that wrong and falls through to something else.

for a principal

Judge whether a debugging affordance with this blast radius should be configurable on production hardware at all, and what your configuration baseline asserts about it.

## One bit, and what it claims The TACACS+ header's `flags` byte carries two defined bits: `TAC_PLUS_UNENCRYPTED_FLAG := 0x01` and `TAC_PLUS_SINGLE_CONNECT_FLAG := 0x04`. The first is the one that matters for payload protection, and its meaning is narrow and literal: **the sender did not obfuscate this body**. It is not a request, not a negotiation and not a capability advertisement. It reports what was done to the bytes that follow. Because the flag sits in the cleartext header, a receiver can act on it before attempting to unmask anything — which is the point. Without it, a peer handed an unmasked body would compute a pad, XOR it into structured data, and produce nonsense. ## The rules, at the strength the specification gives them | Clause | Who it binds | Strength | Requirement | |---|---|---|---| | Section 4.1 | all deployments | SHOULD | the flag is clear | | Section 4.1 | production deployments | MUST NOT | the flag is not used | | Section 4.5 | the receiver of a request | MUST | drop a request that has it set | | Section 10.5.2 | the server | MUST | reject connections on which it is set | | Section 10.5.2 | the client, that is the network device | MUST NOT | set it | | Section 10.5.2 | the client | MUST | require explicit configuration before clear text can be enabled | | Section 10.5.2 | a client seeing a mismatch | MUST | close the TCP session and treat the response as a FAIL | The mixture is deliberate, and a candidate who reports it accurately is showing they read the document rather than a summary of it. Section 4.1's "SHOULD be clear" is advice with a recognised exception — a development bench where a body has to be readable in a capture. "MUST NOT be used in production" removes that exception everywhere real traffic runs, and the receiver-side MUSTs make the rule enforceable rather than aspirational. ## Why a mismatch is a FAIL and not an ERROR This is the distinction that carries the most consequence on the whole branch: - **ERROR** means the server's processing did not complete and the result cannot be applied. A client receiving ERROR **MUST** behave as though the server were unreachable, which sends it on to whatever comes next in its configuration. - **FAIL** means processing completed and the answer is no. A device that expected an obfuscated body and received an unobfuscated one has not hit a reachability problem — it has hit a peer behaving outside the configuration both sides were meant to share. Treating that as ERROR would let an attacker who can inject a single clear-text reply push the device off this server and onto whatever comes next. Requiring **FAIL**, together with closing the TCP session, makes the anomaly terminal for that exchange instead of a lever. ## Why a clear-text mode exists at all Protocol development and troubleshooting. When you are implementing the wire format, a capture in which the body is legible is worth a great deal, and the alternative — instrumenting both endpoints to dump their own pads — is worse. RFC 8907 keeps that door open and then narrows it hard: the device must be explicitly configured before it can use clear text, the flag must never be used in production, and any server that receives it rejects the connection. ## What this looks like on an unwatched link Consider a railway signalling estate whose trackside routers sit at the end of long cable runs nobody inspects between maintenance windows. The flag is the protocol's only in-band statement about whether the body was protected, and like everything else in the header it is unauthenticated. The mitigations are therefore all configuration-side rather than cryptographic: - the device is configured to expect obfuscation, so an unobfuscated reply is a FAIL and the TCP session closes; - the server rejects any connection that arrives with the flag set, so an attacker cannot simply speak clear text at it; - neither peer can be nudged into clear text without a deliberate configuration change on the device. What the flag cannot do is make the obfuscated case safe. Clearing it only means the `pseudo_pad` was applied, and that pad still provides no integrity, no replay protection and no forward secrecy. The flag is about **whether** the mask was used, never about how good the mask is. ## One inversion to keep straight The same bit means the opposite thing on the TLS transport RFC 9887 defines: there, every packet **MUST** have it set, because TLS is doing the protecting and the pad is not applied. Any statement about this flag has to name which transport it is about.

  • Why must a device that expected obfuscation treat a clear-text reply as a FAIL rather than an ERROR?
    ERROR tells the device that processing did not complete, so it must behave as if the server were unreachable and look elsewhere. That turns a single injected clear-text reply into a way of pushing the device off its server. FAIL is a completed "no", and it is paired with closing the TCP session so the exchange cannot continue.
  • If the flag is unauthenticated, why is it worth anything?
    It is not a control against an attacker — it is how two honest peers avoid unmasking bytes that were never masked. Its security value comes from the receiver-side rules around it: a server rejects connections carrying it, and a device that expected obfuscation refuses the exchange outright rather than continuing in the clear.
  • Where is clear-text mode legitimately useful?
    On an isolated bench during protocol implementation or troubleshooting, where reading the body in a capture is the whole point. RFC 8907 confines it there by requiring explicit configuration on the device before it can be enabled and by forbidding its use in production.

saying these in an interview costs you the question

  • Says the flag being set means the body is encrypted.
  • Treats clear text as acceptable on a trusted management network.
  • Claims a device may enable clear text without explicit configuration.
  • Says a flag mismatch should be retried on the same connection.
  • Quotes Section 4.1's SHOULD as though every clause were a MUST.
  • Thinks clearing the flag makes the body properly protected.