shadow1ng/fscan · error
ReadApplicationTag bad tag
Error message
ReadApplicationTag bad tag
What it means
In the long tag form (tag > 30), ReadApplicationTag validates the identifier byte and then reads the actual tag number byte; if that byte does not equal the requested tag, the parsed application tag is the wrong one and this error is returned.
Source
Thrown at libs/grdp/protocol/t125/ber/ber.go:164
func WriteBoolean(b bool, w io.Writer) {
bb := uint8(0)
if b {
bb = uint8(0xff)
}
WriteUniversalTag(TAG_BOOLEAN, false, w)
WriteLength(1, w)
core.WriteUInt8(bb, w)
}
func ReadApplicationTag(tag uint8, r io.Reader) (int, error) {
bb, _ := core.ReadUInt8(r)
if tag > 30 {
if bb != (CLASS_APPL|PC_CONSTRUCT)|TAG_MASK {
return 0, errors.New("ReadApplicationTag invalid data")
}
bb, _ := core.ReadUInt8(r)
if bb != tag {
return 0, errors.New("ReadApplicationTag bad tag")
}
} else {
if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
return 0, errors.New("ReadApplicationTag invalid data2")
}
}
return ReadLength(r)
}
func WriteApplicationTag(tag uint8, size int, w io.Writer) {
if tag > 30 {
core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|TAG_MASK, w)
core.WriteUInt8(tag, w)
WriteLength(size, w)
} else {
core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), w)
WriteLength(size, w)
}View on GitHub (pinned to 95cc12e753)
Solutions
- Log/inspect the received tag byte to see which PDU the server actually sent
- Verify X.224 negotiation succeeded (check the CC result byte) before parsing CONNECT_RESPONSE
- Fix any upstream desync so the tag byte is read at the correct offset
- Compare the server's PDU numbering against the T.125 spec and adjust the expected tag constant if it is a known variant
Example fix
// before
if bb != tag {
return 0, errors.New("ReadApplicationTag bad tag")
}
// after
if bb != tag {
return 0, fmt.Errorf("ReadApplicationTag bad tag: expected %d, got %d", tag, bb)
} Defensive patterns
Strategy: try-catch
Validate before calling
// peek the tag number byte and compare before full parse
if len(buf) > pos+1 && buf[pos+1] != expectedTag {
return fmt.Errorf("server sent application tag %d, expected %d", buf[pos+1], expectedTag)
} Try / catch
n, err := ber.ReadApplicationTag(101, r)
if err != nil {
if strings.Contains(err.Error(), "bad tag") {
// server sent a different PDU — inspect which one and handle
}
return err
} Prevention
- Verify X.224 negotiation succeeded so the server actually sends CONNECT_RESPONSE
- Log unexpected PDU tag numbers to identify server variants
- Keep parsing state consistent so the tag byte is read at the right offset
When it happens
Trigger: ReadConnectResponse requesting a specific high application tag (e.g. 101) but the stream carries a different application tag number at that position — a different PDU arrived where CONNECT_RESPONSE was expected.
Common situations: Server rejecting negotiation and sending a different application-tagged PDU; desynced parsing misreading content bytes as the tag byte; nonstandard server PDU numbering.
Related errors
- ReadApplicationTag invalid data
- ReadApplicationTag invalid data2
- invalid ber tag
- enumerate size is wrong, get %v, expect 1
- BER length may be 1 or 2
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/0b2a7ff44f802b22.
Report an issue: GitHub.