hyperledger/fabric · critical
chaincode %s attempted to write to the namespace of LSCC
Error message
chaincode %s attempted to write to the namespace of LSCC
What it means
VSCC detected that the application chaincode's write set contains writes to the 'lscc' namespace. Deploy/upgrade are the only legitimate writers of LSCC and are performed by the system, so an application transaction writing to LSCC is rejected with TxValidationCode_ILLEGAL_WRITESET as a security measure (preventing unauthorized chaincode definition changes).
Source
Thrown at core/committer/txvalidator/v14/vscc_validator.go:177
writesToNonInvokableSCC = true
}
}
// we've gathered all the info required to proceed to validation;
// validation will behave differently depending on the type of
// chaincode (system vs. application)
if !IsSysCC(ccID) {
// if we're here, we know this is an invocation of an application chaincode;
// first of all, we make sure that:
// 1) we don't write to LSCC - an application chaincode is free to invoke LSCC
// for instance to get information about itself or another chaincode; however
// these legitimate invocations only ready from LSCC's namespace; currently
// only two functions of LSCC write to its namespace: deploy and upgrade and
// neither should be used by an application chaincode
if writesToLSCC {
return peer.TxValidationCode_ILLEGAL_WRITESET,
errors.Errorf("chaincode %s attempted to write to the namespace of LSCC", ccID)
}
// 2) we don't write to the namespace of a chaincode that we cannot invoke - if
// the chaincode cannot be invoked in the first place, there's no legitimate
// way in which a transaction has a write set that writes to it; additionally
// we don't have any means of verifying whether the transaction had the rights
// to perform that write operation because in v1, system chaincodes do not have
// any endorsement policies to speak of. So if the chaincode can't be invoked
// it can't be written to by an invocation of an application chaincode
if writesToNonInvokableSCC {
return peer.TxValidationCode_ILLEGAL_WRITESET,
errors.Errorf("chaincode %s attempted to write to the namespace of a system chaincode that cannot be invoked", ccID)
}
// validate *EACH* read write set according to its chaincode's endorsement policy
for _, ns := range wrNamespace {
// Get latest chaincode version, vscc and validate policy
txcc, vscc, policy, err := v.GetInfoForValidate(chdr, ns)
if err != nil {View on GitHub (pinned to 2736b63f8f)
Solutions
- Remove any chaincode logic that writes keys into the lscc namespace; use the standard lifecycle (deploy/upgrade) to change chaincode definitions.
- Sanitize user-supplied keys in your chaincode so they cannot be crafted to target lscc.
- Upgrade channel validation policy / use newer Fabric lifecycle where system-chaincode namespaces are separately enforced.
Example fix
// before
stub.PutState("lscc/mycc/name", []byte("evil"))
// after: write only within your own chaincode's namespace
stub.PutState("myccstate", value) Defensive patterns
Strategy: validation
Validate before calling
for _, ns := range txRWSet.NsRwSets {
if ns.NameSpace == "lscc" {
return fmt.Errorf("write set contains forbidden write to system chaincode namespace 'lscc'")
}
} Type guard
func writesOnlyAppNamespaces(rwset *rwset.TxRwSet, appNS []string) bool {
allowed := map[string]bool{}
for _, n := range appNS {
allowed[n] = true
}
for _, ns := range rwset.NsRwSets {
if !allowed[ns.NameSpace] {
return false
}
}
return true
} Try / catch
if writesToLSCC {
logger.Warnf("tx rejected: chaincode %s attempted to write to the namespace of LSCC", ccID)
return peer.TxValidationCode_ILLEGAL_WRITESET, nil
} Prevention
- Never call PutState with keys intended for the lscc keyspace; change definitions via standard lifecycle only.
- Sanitize all user-supplied state keys in chaincode code.
- Review chaincode diffs for any system-chaincode namespace strings before deployment.
- Use the newer Fabric lifecycle (chaincode-as-a-service / _lifecycle) where such writes are structurally prevented.
When it happens
Trigger: A chaincode performs a PutState on key(s) that land in the lscc namespace — e.g. calling stub.PutState with keys targeting lscc's scope — or a chaincode attempts to emulate deploy/upgrade by writing to lscc directly.
Common situations: Malicious or naive chaincode trying to modify its own definition or another chaincode's entry; applications passing user-controlled keys that were crafted to collide with lscc keyspace on old Fabric versions; tests probing system-chaincode writes.
Related errors
- duplicate namespace '%s' in txRWSet
- error unmarshalling ChaincodeHeaderExtension
- nil ChaincodeId in header extension
- nil ChaincodeId in ChaincodeAction
- invalid chaincode ID
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/725f37d342a0a93f.
Report an issue: GitHub.