CERT C Programming Language Secure Coding Standard

R

Robert Seacord

The CERT/CC has just deployed a new web site dedicated to developing
secure coding standards for the C programming language, C++, and
eventually other programming language.

We have already developed significant content for the C programming
language that is available at:

https://www.securecoding.cert.org/

by clicking on the "CERT C Programming Language Secure Coding Standard"
link.

We are depending on the active involvement of the C programming language
community (you) and ISO/IEC JTC1/SC22/WG14 to make this effort a
success. I invite you to participate in this effort by reviewing
content on the web site and providing comments, or by contributing new
rules and recommendations for secure c coding. These can be sent to me
directly or to secure-coding at cert dot com.

I am attaching a press-release like article we wrote below to announce
the effort. There is also a rationale section on the web site that
provides more details as to what we are doing and why.

Thanks,
rCs

-------------------

The Carnegie Mellon Software Engineering Institute (SEI) CERT® Program
has deployed a secure coding Web site at www.securecoding.cert.org to
cooperate with the software development community in codifying a
practical and effective set of secure coding practices for popular
programming languages. These coding practices can then be used by
software developers to eliminate vulnerabilities before software is
operationally deployed.

The purpose of this project is that the practices can be used by
developers for professional development and as the basis for
organizational coding standards supporting the quality of their products.

Jeffrey Carpenter, manager of the CERT Coordination Center, says that
the project is part of a larger secure coding initiative within the
CERT/CC to eliminate dangerous coding practices that can result in
exploitable software vulnerabilities. According to Carpenter, "CERT is
in a unique position to coordinate development of a set of secure coding
practices because of its long history in analyzing and responding to
software vulnerabilities."

CERT's initial efforts are focused on the development of secure coding
practices for the C and C++ programming languages. CERT senior
vulnerability analyst Robert Seacord is leading the secure coding
initiative. Seacord is a leading authority on secure coding, author of
the book Secure Coding in C and C++ [Seacord 05], and technical expert
for the ISO/IEC JTC1/SC22/WG14 international standardization working
group for the programming language C.

"C and C++ were selected because a large percentage of critical
infrastructures are developed and maintained using these programming
languages," Seacord says. "C and C++ are popular and viable languages
although they have characteristics that make them prone to security flaws."

"Today's dependency on networked software systems has been matched by an
increase in the number of attacks against governments, corporations,
educational institutions, and individuals. These attacks result in the
loss and compromise of sensitive data, system damage, lost productivity,
and financial loss," says Seacord. To address this growing threat, the
introduction of software vulnerabilities during development and ongoing
maintenance must be significantly reduced, if not eliminated.

CERT recognizes that there are a number of available resources, both
online and in print, containing coding guidelines, best practices,
suggestions, and tips. The Motor Industry Software Reliability
Association (MISRA) developed guidelines for the use of the C language
in critical systems [MISRA 04], and more recently the U.S. Department of
Homeland Security launched its Build Security In web site
(https://buildsecurityin.us-cert.gov) to promote the codification of
practices and rules. These sources, however, do not provide a
prescriptive set of secure coding practices that can be uniformly
applied in the development of a software system.

"Without secure coding practices, software vulnerability reports are
likely to continue on an upward trend," Seacord says. "At CERT/CC, we
have had nearly 4,000 vulnerabilities reported in the first half of
2006. To stop the threats, we need to develop secure software from the
outset."

The secure coding practices proposed by CERT are based on standard
language versions as defined by official or de facto standards
organizations such as ISO/IEC. CERT is not an internationally recognized
standards body, but plans to work with organizations such as ISO/IEC to
advance the state of the practice in secure coding. The ISO/IEC
JTC1/SC22 WG14 international standardization working group for the
programming language C, for example, has offered to provide direction in
the development of the C language secure coding practices and to review
and comment on drafts of the informal CERT standard.

According to WG14 convener John Benito, "The secure coding standard is
going in the correct direction, and I have confidence the final product
will be useful to the community."

CERT is also working with standards groups, such as the ISO/IEC working
group on Guidance for Avoiding Vulnerabilities through Language Use
(OWGV). While the ISO/IEC group is working on providing
language-independent guidance, the CERT effort is working on developing
and consolidating the language-specific guidance that provides the
foundations for the ambitious goals of OWGV.

Jim Moore, convener of OWGV, states that "CERT's efforts in identifying
and documenting secure coding practices for C and C++ will contribute to
the standardization of these practices and advance the goals of the OWGV."

Community Involvement

The success of the secure coding standards depends largely on the active
involvement of members of the secure software and C and C++ development
communities. Rules and recommendations for each coding practice are
solicited from the communities involved in the development and
application of each programming language, including the formal or de
facto standard bodies responsible for the documented standard.

These rules and recommendations are edited by CERT senior members of the
technical staff for content and style, and placed in Secure Coding
Standards Web site for comment and review. The user community is invited
to discuss and comment on the publicly posted content. Once a consensus
develops that the rule or recommendation is appropriate and correct, the
final rule is incorporated into the coding standard.

Once practices are documented, tools can be developed or modified to
verify compliance. Compliant software systems may then be certified as
compliant by a properly authorized certification body. Seacord also
envisions a training and development program to educate software
professionals regarding the appropriate application of secure coding
practices.

The development of secure coding practices is a necessary step to stem
the ever-increasing threat from software vulnerabilities. CERT's goal is
that the enumeration of secure code practices will allow for a common
set of criteria that can be used to measure and evaluate software
development efforts.

The public can review or comment on the existing content at the secure
coding Web site or submit new ideas for secure coding practices by
e-mailing (e-mail address removed). Robert Seacord can be reached at
(e-mail address removed).


*******************************
[1] Seacord, R. Secure Coding in C and C++. Addison-Wesley, 2005. See
http://www.cert.org/books/secure-coding for news and errata.

[2] MISRA C: 2004 Guidelines for the use of the C language in Critical
systems. MIRA Limited. Warsickshire, UK. October 2004. ISBN 0 9524156.
 
E

ena8t8si

Robert said:
The CERT/CC has just deployed a new web site dedicated to developing
secure coding standards for the C programming language, C++, and
eventually other programming language.

We have already developed significant content for the C programming
language that is available at:

https://www.securecoding.cert.org/

by clicking on the "CERT C Programming Language Secure Coding Standard"
link.

Comments:

1. A reasonable set of suggestions.

2. Many of the rules/recommendations are coding practices
rather than standards. To be a standard the question of
whether the standard is met must be objective and unambiguous.
"Strive for clarity", for example, may be good advice but
it cannot be offered as a "standard".

3. The explanation in ARR31-C is wrong. In function
prototypes or definitions, using

void func(char *a)

or

void func(char a[])

are exactly equivalent whether in the same file or in
different files. It's declarations outside of function
parameter lists where the two forms of declaration
result in different types.
 
R

rCs

comments below.
1. A reasonable set of suggestions.

thanks. 8^)
2. Many of the rules/recommendations are coding practices
rather than standards. To be a standard the question of
whether the standard is met must be objective and unambiguous.
"Strive for clarity", for example, may be good advice but
it cannot be offered as a "standard".

this is supposed to be a "coding standard" which include a set of rules
and recommendations for developers to follow. the rules are meant to
be verifiable, which of course requires they be unambigous. we also
have recommendations which should also be clear, but not necessarily
verifiable. "strive for anything" would clearly be a recommendation.
i couldn't find "Strive for clarity", but there is MSC01-A. Strive for
Logical Completeness which is a recommendation and, I think, pretty
clear in its meaning (once you read the description).
3. The explanation in ARR31-C is wrong. In function
prototypes or definitions, using
void func(char *a)
or
void func(char a[])
are exactly equivalent whether in the same file or in
different files. It's declarations outside of function
parameter lists where the two forms of declaration
result in different types.

hmm, i read this in "Safer C: Developing Software for High-integrity
and Safety-critical Systems" by Les Hatton and I'm 99.5% sure I
verified this in my own tests.

there is a separate suggestion that this rule needs to be broadened,
which i plan to evaluate further.

anyway, thanks for having a look and providing some feedback.

rCs
 
E

ena8t8si

rCs said:
comments below.


thanks. 8^)

You're welcome!
this is supposed to be a "coding standard" which include a set of rules
and recommendations for developers to follow. the rules are meant to
be verifiable, which of course requires they be unambigous. we also
have recommendations which should also be clear, but not necessarily
verifiable.

Yes, I thought that might be how you were dividing it.
I couldn't always tell. However, since there are both,
you might consider "Secure Coding Practices and Standards".
"strive for anything" would clearly be a recommendation.
i couldn't find "Strive for clarity", but there is MSC01-A. Strive for
Logical Completeness which is a recommendation and, I think, pretty
clear in its meaning (once you read the description).

Yes, I think I combined the recommendations for clear
comments and Strive for Logical Completeness to get
Strive for Clarity. Anyway you got my drift.

But since you mention it let's look at the Logical Completeness
recommendation. Consider

enum WidgetEnum { WE_X, WE_Y, WE_Z } widget_type;
...

switch (widget_type) {
case WE_X: ...
case WE_Y: ...
case WE_Z: ...
}

Does the Logical Completeness recommendation mean to
complain about this switch() statement or not (because
there is no default: case)? As written, the switch is
complete, but if another enum value were added it wouldn't
be. However, depending on the tools being used, it can
be better to leave off the default: so that the compiler
can remind us that we need to add a case.

It's details like these that make writing coding standards
hard.

Another example - the recommendation to use a high warning
level. I agree, but what is meant by "high" is different
for different people. It would help the discussion and
also help strengthen the standard if the different sorts
of conditions that should be warned on if possible were
included, as (examples only!):

variable possibly used without being initialized
variable never used
signed/unsigned comparison
character literal assigned to non-const pointer
...

Maybe another way of saying this is that you're on the
right track but there needs to be more specifics.
3. The explanation in ARR31-C is wrong. In function
prototypes or definitions, using
void func(char *a)
or
void func(char a[])
are exactly equivalent whether in the same file or in
different files. It's declarations outside of function
parameter lists where the two forms of declaration
result in different types.

hmm, i read this in "Safer C: Developing Software for High-integrity
and Safety-critical Systems" by Les Hatton and I'm 99.5% sure I
verified this in my own tests.

there is a separate suggestion that this rule needs to be broadened,
which i plan to evaluate further.

There's no question that the rule applies to top level
declarations. And the rules C has for type compatibility
aren't always obvious, so it's good to point out common
cases that can lead to bad behavior.
anyway, thanks for having a look and providing some feedback.

No problem. I'm surprised more of the regulars didn't
say anything, this effort looks like it's going in
the right direction.

By the way, you might want to add a memory management
rule:

Don't cast the return value of malloc (when used in
simple assignment).

The reasoning being, code like

int *p;

p = (int *) malloc( sizeof *p );

can mask errors if there is no earlier declaration of
malloc. That's also true of functions generally, but
the problem seems especially common with malloc.

That reminds me of something else, which is function
prototypes. I suggest adding a rule

All function calls and function defintions should
be preceded by a function prototype.

And, if possible, exactly one, and checked by the
compiler. (Of course I mean prototype to include
declaring the types of the function's parameters.)
 
K

kuyper

rCs wrote:
....
this is supposed to be a "coding standard" which include a set of rules
and recommendations for developers to follow. the rules are meant to
be verifiable, which of course requires they be unambigous. we also
have recommendations which should also be clear, but not necessarily
verifiable.

That's precisely the point. If it's not verifiable, it doesn't belong
in something called a "coding standard". You could call it "coding
advice", but it isn't a coding standard. With something that vague, it
doesn't even qualify as a guideline - a guiide line is something that
identifies the correct path sufficiently precisely to ensure your
arrival at your destination; programming advice that vague doesn't
qualify for the metaphor.
3. The explanation in ARR31-C is wrong. In function
prototypes or definitions, using
void func(char *a)
or
void func(char a[])
are exactly equivalent whether in the same file or in
different files. It's declarations outside of function
parameter lists where the two forms of declaration
result in different types.

hmm, i read this in "Safer C: Developing Software for High-integrity
and Safety-critical Systems" by Les Hatton and I'm 99.5% sure I
verified this in my own tests.

What form did your test take? Did you try building the examples of
non-compliant and compliant code that are provided with ARR31-C? Those
examples demonstrate, correctly, that if something is defined as a
global pointer in one translation unit(TU), and incompletely declared
as a global array of unspecified size in another TU, the two
declarations are indeed incompatible in a way that can cause serious
trouble.

However, the advice that goes with the example is about the declaration
of function arguments, not the declaration of global variables. That
advice is wrong, and has nothing to do with the example given. The two
declarations of func() are exactly equivalent, and it doesn't matter
whether they're in the same TU or different TUs.
 
R

rCs

the points you make below are exactly the points i was trying to make
in ARR31-C. i've tried to make it a little clearer, and may revise
further tomorrow.

What form did your test take? Did you try building the examples of
non-compliant and compliant code that are provided with ARR31-C? Those
examples demonstrate, correctly, that if something is defined as a
global pointer in one translation unit(TU), and incompletely declared
as a global array of unspecified size in another TU, the two
declarations are indeed incompatible in a way that can cause serious
trouble.

However, the advice that goes with the example is about the declaration
of function arguments, not the declaration of global variables. That
advice is wrong, and has nothing to do with the example given. The two
declarations of func() are exactly equivalent, and it doesn't matter
whether they're in the same TU or different TUs.

rCs
 
C

CBFalconer

Robert said:
The CERT/CC has just deployed a new web site dedicated to developing
secure coding standards for the C programming language, C++, and
eventually other programming language.

We have already developed significant content for the C programming
language that is available at:

https://www.securecoding.cert.org/

by clicking on the "CERT C Programming Language Secure Coding Standard"
link.
..... snip ...

I took a more or less random look at that site, and found this:

STR30-C. Do not attempt to modify string literals
STR31-C. Do not copy data from an unbounded source to a
fixed-length array
STR32-C. Allocated adequate space when copying bounded strings
STR33-C. Guarantee that all strings are null-terminated
STR34-C. Do not truncate strings while copying

which seems pretty banal to me.

First, it is not legal to modify string literals, such attempts
result in undefined behaviour. With gcc at least, you can arrange
for them to be declared as const, and thus get compiler warnings.

Second and third, the only kind of array available in C is a fixed
length array. The programmer needs to ensure that the length is
adequate. The same applies to copying strings. You may be
thinking of the sort of thing that my ggets handles - see:

<http://cbfalconer.home.att.net/download/>

or that strlcpy/strlcat handles. See same place.

Fourth, without a zero (not null) termination, a char array is not
even a string.

Fifth, why not truncate strings? The usefulness depends on the
circumstances. Truncation is certainly always more attractive than
overflowing storage.

My conclusion - the advice is worthless to all but the rankest
beginners. A reading of the C-faq is more productive.

USE maineline address!
 
B

Bill Pursell

Robert said:
The CERT/CC has just deployed a new web site dedicated to developing
secure coding standards for the C programming language, C++, and
eventually other programming language.

I downloaded some of the code snippets, and the first one
I tested compiled with the following warnings:

[Chapter_3]$ gcc -Wall -pedantic Figure3-12-unix.c
Figure3-12-unix.c: In function `main':
Figure3-12-unix.c:27: warning: implicit declaration of function
`atexit'
Figure3-12-unix.c:29: warning: control reaches end of non-void function

I am not sure it's worth looking too closely if the very first sample
behaves like that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top