Secure Coding Principles Overview
Secure Coding Principles Overview
Module1
1|Page
2. Difference Between Robustness and Security:
o A robust program handles errors and prevents unintended behaviors.
o A program is secure if it prevents unauthorized actions or breaches,
depending on the policies and procedures in place.
o Robustness is essential for security, but a robust program may not always
be secure depending on its context.
3. Context Matters:
o Security is determined by the program, its environment, and the
procedures used.
o Example:
▪ A mathematically proven secure system can still be insecure if
procedural flaws (e.g., no passwords, open internet connection)
exist.
▪ A vulnerable system might remain secure if its usage policies
eliminate potential attack vectors (e.g., never connecting to a
network).
4. Key Concepts:
o Privileges:
Users and programs operate with specific rights (e.g., read, write).
Escalated privileges (e.g., admin or root access) can lead to vulnerabilities
if not managed properly.
o Protection Domain:
This includes all resources a program can access and actions it can
perform. Minimizing the protection domain limits potential damage from
attacks.
Secure programming combines careful coding, understanding of the operating
environment, and strict adherence to procedures to prevent vulnerabilities and
ensure system integrity.
2|Page
Aspect Explanation
3|Page
Aspect Explanation
Risks of libraries and Reusing libraries inherits their bugs; assumptions about
assumptions environments can lead to vulnerabilities.
Assumptions: Always check your assumptions. Think beyond the obvious (out-of-the-box
thinking) and question what you trust.
Interactions and Dependencies: Pay attention to how the program interacts with external and
internal components, such as user inputs, network connections, and dependencies like
cryptography.
4|Page
Error Messages: Be cautious with how much information is revealed in error messages, as
overly detailed messages can assist attackers.
Security Assumptions in System Design: Understand the limitations of systems (e.g., root
access in Unix/Linux), and how encryption can be bypassed if the root user is malicious.
3. Input Validation:
o Validate user identity and handle naming conflicts (e.g., users with the same
name, or websites masquerading as others).
o Cryptography: Both its correct implementation and proper use are critical to
avoid security flaws.
o Be cautious about the behavior of library functions and other programs your code
depends on, especially in handling inputs from the environment, such as
environment variables, which can be exploited if not handled properly.
6. Language-Specific Issues:
5|Page
o Pay attention to type checking and potential mismatches (e.g., signed vs.
unsigned numbers) to avoid errors in program execution.
8. Thought Exercise:
o Network servers should ideally run with minimal privileges (e.g., as "nobody" on
Linux), reducing the risk of exploitation.
3. Local Servers:
o Local servers should also limit their environment and be cautious when inherited
from the process that started them, as it could include dangerous configurations.
o The best practice is for servers to wipe the environment and install their own
secure environment before starting.
6|Page
o Setuid (Set User ID) and Setgid (Set Group ID) programs allow a program to run
with the permissions of the file owner (e.g., root), not the user executing it. These
programs are often exploited if the environment isn't cleaned or validated.
5. Client-Server Interaction:
o It's a mistake to assume that a client checks the input fully and the server doesn't
need to. If a server doesn't validate incoming data, a malicious client can exploit
vulnerabilities.
o Clients, such as web browsers, should be careful about what information they
send back to the server, including environment variables and cookies, as this data
can be manipulated.
o The ambiguity arises from the RFCs describing the TCP behavior in conflicting
ways, leaving the implementation open to attack.
7|Page
Summary of Key Security Considerations:
• Be cautious with environment handling in Setuid and Setgid programs, as these can be
exploited if improperly configured.
• Both servers and clients need to perform thorough input validation to avoid
vulnerabilities.
• Consider the security of the entire communication flow, including the ambiguities in
protocols like TCP that could lead to attacks like the Land Attack.
• In cryptographic systems, be aware of the assumptions made about the integrity of the
environment and the anonymity of identifiers, as these can impact the overall security and
privacy.
• Privileges are not just about special permissions (like Setuid/Setgid). It's also about who
runs the program. For example, if a superuser or sysadmin runs a program, it gets their
high-level privileges.
2. What is an Attack?:
• An attack is anything that tries to break the rules set by the security policy. If it breaks the
rules, the attack is successful; if it doesn't, it's a failure.
Here are the questions with their correct answers structured clearly:
Question 1:
8|Page
• Robust programming deals with errors whether or not they are a security problem; secure
programming deals with errors that are security problems.
Question 2:
Fill in the blanks with the correct phrases from options below:
Security policies _______ and security mechanisms ______.
Answer:
• Security policies say what is and is not allowed, and security mechanisms enforce the policy.
Question 3:
Consider a program that uses a cryptographic library obtained from a third party. Which of the following is
most likely to be true?
Answer:
• The programmer must take care that all inputs to the library are checked to ensure they match what
the library expects.
Question 4:
When a user tries to log in, she enters a login name and a password. The computer checks that the login name is
that of an authorized user and if not, gives the error message "Bad login name" and requests another name and
password. If the login name is valid, it checks the password and if that does not correspond to the named user, it
gives the error message "Bad password" and requests another password. Which of the following best describes
this procedure?
Answer:
• It is poor security, because a user can tell whether a guessed login name is a valid one.
Question 5:
Question 6:
Question 7:
9|Page
Module2
3. Practical Understanding:
o POLA and PLP are often seen as synonymous, but their differences are
nuanced.
o For most practical purposes, recognizing the two as similar suffices unless
you're a system developer.
4. Application in Systems:
o Question: Do Unix-like systems (e.g., FreeBSD, Linux) or Windows
enforce least privilege?
o This is explored further in exercises, with the principle being a critical
aspect of system security.
10 | P a g e
1. Definition of Fail-Safe Defaults:
o Inspired by Cold War "fail-safe points," where bombers halt unless explicitly instructed
to proceed.
▪ Default Denial: Deny access by default and grant explicit permissions only
when necessary.
▪ Fail Securely: When a failure occurs, the system must remain secure without
exposing information or granting privileges.
o Default Denial:
▪ Start with "deny, deny, deny" and only explicitly allow permissions.
o Secure Failure:
▪ During failures, the system's security should remain intact, matching the security
level before the failure.
▪ Instead of allowing all characters and blocking dangerous ones (e.g., |, $, !), only
permit safe characters like letters, digits, and hyphens.
o Prevents unintended security lapses by ensuring strict and clear rules for granting access
and handling failures.
11 | P a g e
1. Definition of Economy of Mechanism:
o Easier Analysis:
o Simpler Fixes:
▪ Straightforward designs make troubleshooting and fixing issues faster and more
efficient.
o Avoids Confusion:
▪ Complexity may confuse both attackers and legitimate users, but confusion does
not inherently improve security.
o Interfaces:
o Interactions:
4. Key Takeaway:
o Complexity often adds confusion, not security. Prioritize simplicity to create secure and
maintainable systems.
o Many systems, like Windows, Linux, and Unix, check permissions only when a file is
opened.
o Once opened, the file handle or descriptor is used without further permission checks,
even if permissions change afterward.
12 | P a g e
3. Key Concept: Capabilities:
o A capability includes:
▪ Example: A file opened with write permissions remains writable via the
descriptor, even if write permissions are revoked.
4. Key Takeaway:
o For true security, access permissions should be rechecked during every access attempt,
not just at the initial access point.
o Often referred to as defense in depth, similar to a medieval castle with multiple layers of
protection (e.g., moat, outer wall, inner wall, keep, and dungeon).
o Commercial Context: Large checks (e.g., over $100,000) requiring approval from two
individuals.
▪ This specific case is also called separation of duty but follows the same
principle.
o SU (Substitute User):
4. Key Takeaway:
----------------------------------------------------------------------------------------------------------------------------- --
13 | P a g e
1. Principle of Open Design:
o Definition:
▪ This principle rejects the idea of "security by obscurity," where security depends
solely on keeping the design secret.
o Important Clarification:
▪ The goal is for a system to remain secure even if the design or implementation is
discovered.
o CSS Overview:
▪ The player uses various keys (player key, disc key, and title key) to decrypt
content for playback.
o Security by Obscurity:
▪ The DVD Copyright Control Association (DCCA) sued to stop distribution, but
when the source code for CSS was submitted in court, it was accidentally made
public.
o Outcome:
▪ The leaked code was downloaded 20,000 times and widely distributed, exposing
weaknesses in CSS.
o Aggregation of Information:
▪ During the Gulf War, the Associated Press (AP) used publicly available data to
identify the locations of US military bases in Iraq.
▪ This data was initially considered secret but was inadvertently made public.
o Lesson:
14 | P a g e
4. Key Takeaway:
1. Definition:
o The Principle of Least Common Mechanism states that systems should avoid sharing
common resources (such as CPUs, memory, or networks) between users or processes.
Sharing resources can create covert channels, where unintended information can be
leaked between isolated entities.
o Covert Channels: Information can be passed covertly through shared resources. For
instance, manipulating CPU time to encode bits of information.
o Side-Channel Attacks: These attacks exploit system behaviors like power usage or
execution time to gather sensitive information, such as cryptographic keys.
3. Isolation Techniques:
o Virtual Machines: Programs or processes are isolated within a virtual machine that
simulates a separate system. This prevents sharing of underlying resources.
o Attack Method: In a DDoS attack, attackers flood a bank's web server with requests,
overwhelming the shared network connection and preventing legitimate users from
accessing the server.
o Principle Connection: The common network channel between the attackers and
legitimate users is the shared resource that makes this attack possible.
o Countermeasure:
▪ Banks can mitigate the attack by isolating malicious traffic from legitimate
users. This can be done by redirecting suspicious traffic to another network or
blocking it at the router level while allowing legitimate connections to proceed.
5. Key Takeaway:
o The principle emphasizes minimizing shared resources to reduce the risk of information
leakage and to prevent attacks that exploit these shared channels. Proper isolation
mechanisms, like virtual machines and sandboxes, are essential for enforcing this
principle.
----------------------------------------------------------------------------------------------------------------------------- ----
15 | P a g e
Least Astonishment:
1. Definition
• Least Astonishment means that security mechanisms should be designed to align with users'
expectations and understanding.
• The goal is to minimize surprise for the user by designing systems that behave in a predictable
and intuitive way.
2. Core Idea
• Security should not confuse the user. Users should understand why something works the way it
does without being surprised or frustrated.
• The system should match the user's mental model of how things should operate.
3. Examples
• Password Example:
o Logging into a system with a username and password is a familiar process. It’s expected
and doesn’t surprise users.
o However, if the system unexpectedly asked for a urine specimen for verification, it
would confuse the user. This violates the principle of Least Astonishment.
• Installation Example:
o Software installation typically asks for simple information, like a serial number. If it
unexpectedly asks for your bank account number, that would be astonishing and break
the user's expectations.
4. Security Mechanisms
• Security mechanisms (like passwords) may add some difficulty or extra steps, but they should
not create unnecessary confusion.
• Users should expect and understand security steps, such as entering a password, as part of
normal behavior.
• Psychological Acceptability: This principle suggests that security mechanisms should not make
access difficult.
• Least Astonishment acknowledges that some difficulty is inevitable for security (like passwords),
but it aims to minimize that difficulty.
6. Applications
• Batch Systems: If a system runs without user interaction and asks for a password in advance, it
doesn't surprise the user.
• Interactive Systems: Asking for a password repeatedly in an interactive system violates Least
Astonishment because it creates unexpected behavior that frustrates the user.
16 | P a g e
7. Conclusion
• The principle of Least Astonishment ensures that security is intuitive and user-friendly, avoiding
unnecessary surprises or confusion.
o Secure design principles should be part of the design and implementation process to
make security effective and usable.
o Without these principles, systems may be either too complex to use or ineffective at
providing security.
o To successfully apply these principles, you must deeply understand the goals of the
security mechanisms you use.
o You also need to understand the environment in which the system will be used, as this
impacts how security should be implemented.
o Principles give you guidelines (what to do) but do not tell you how to do it. The details
of how you apply a principle depend on:
o A careful design and thorough analysis of the system are crucial to ensuring the security
principles are properly applied.
o The design must consider all aspects of security, making sure the mechanisms work as
intended in the specific environment.
Conclusion:
• Secure design is not just about implementing security features, but about carefully considering
how they will work, why they are needed, and how they fit within the broader system and
environment
17 | P a g e
Principles of Secure Coding - Secure Programming Design Principles - Week 2
Principle Description
Open Design Security should not depend on the secrecy of the design or implementation.
Least Privilege Subjects should have the minimum privileges necessary to perform their tasks.
Fail-Safe Defaults Default configurations should deny access unless explicitly granted.
Psychological Security mechanisms should be easy to use and understand to prevent users
Acceptability from bypassing them.
18 | P a g e
Module 3
Robust Code refers to writing programs that work well and do not break easily. It means the code should
handle mistakes, unexpected problems, or wrong inputs in a way that prevents the program from crashing.
1. Paranoia: Assume that something could go wrong. Always be cautious and check things carefully.
2. Stupidity: Expect that the user might make mistakes or not know how to use the program. The
program should be able to handle this.
3. Dangerous Implements: Don't let users or programmers change important parts of the program that
could cause problems.
4. Things Can Happen: Even if something seems impossible, assume that future changes might cause
problems. Always check for those situations.
robustness in programming.
summary of key points and what can go wrong with non-robust code, specifically in the context of a
queue implementation in C.
Key Concepts:
• Queue: A structure that follows a Last In, First Out (LIFO) principle. Elements are added and
removed from the end of the queue.
• Queue Operations: Functions like qmanage to create or delete a queue, put to add an element,
and take_off_queue to remove an element.
1. Queue Creation/Deletion:
o Malloc Failure: If the memory allocation fails, it could lead to crashes. Not handling the
NULL pointer from failed malloc could cause the program to crash when trying to access
memory.
o Size Overflow: If the size calculation overflows (e.g., very large sizes on a 32-bit
machine), it could cause a situation where malloc receives a size of zero, leading to
undefined behavior.
o Double Free: If the queue pointer is deleted multiple times (without resetting to NULL),
it could cause the program to crash or become vulnerable to attacks (double free
vulnerability).
19 | P a g e
2. Adding/Removing Elements:
o Pointer Errors: If a pointer to the queue is messed up (e.g., the head or count values are
incorrect), operations on the queue might access invalid memory or lead to incorrect
behavior.
o Overflow/Underflow: If the queue is full or empty, it may either overwrite data or try to
access data that doesn’t exist (like accessing an element from an empty queue), both
causing crashes or undefined behavior.
• Sanity Checks: Ensure that all inputs and operations are checked for validity. For example,
checking whether malloc was successful or checking if the queue is full or empty before adding or
removing elements.
• Error Handling: Properly handle errors like malloc failures, invalid pointers, and invalid
operations (like adding to a full queue or removing from an empty one).
• Memory Management: Always make sure to check whether you’re trying to free a NULL pointer
and prevent double frees.
In a robust version of this code, these issues would be carefully addressed by adding error checks,
validating inputs, and handling unexpected situations gracefully.
---------------------------------------------------------------------------------------------------------------------------
Assume that nothing is In the queue library, instead of trusting that the caller
Paranoia trustworthy unless it’s created will maintain the queue structure consistently, a token is
by the program itself. passed, and the program validates it before using it.
20 | P a g e
Principle Explanation Example
Define error codes clearly and When a queue operation fails, instead of just returning a
associate descriptive messages generic error code, the system also stores an error
Error Handling
with those codes to make message in a buffer, making it easier for the caller to
debugging easier. understand what went wrong.
Use tokens that ensure a queue A nonce is included in the token to make it unique and
Token reference is valid and prevents ensure that once a queue is deleted, the token associated
Management misuse of a deleted or invalid with it cannot be reused. This prevents problems like
queue. double frees or incorrect references.
Avoid vulnerabilities caused by When displaying error messages, the library avoids
Format String format string attacks by format string vulnerabilities by ensuring that all format
Protection controlling the format strings strings are controlled within the library itself, not from
internally. user input.
These principles, when applied in coding, help to ensure that the program behaves predictably, is
secure, and avoids common pitfalls like buffer overflows, crashes, or undefined behavior.
21 | P a g e
In this video, the speaker discusses how well parts of a function work together, specifically focusing on
cohesion. The idea is that when a function performs multiple unrelated tasks, its cohesion is low, which can
make the function harder to understand and maintain. High cohesion means that all parts of a function work
toward a single goal, which makes the code cleaner and conceptually simpler. The recommendation is to
break functions with low cohesion into separate functions.
The speaker demonstrates this by introducing a set of functions to work with queues:
1. Create Queue and Delete Queue: These are separated into two functions to avoid confusion and
maintain high cohesion. Each function has a clear, distinct responsibility: creating a queue or
deleting a queue.
2. Put on Queue and Take off Queue: These functions are introduced to interact with the queue.
Instead of passing a pointer to an integer to store the number, Take off Queue returns the integer
directly to avoid the complexity of checking whether the pointer is valid.
The speaker also highlights the design of a queue structure and the token generation process. The token
is generated in a way that avoids errors related to invalid references and ensures that the function behaves
as expected by validating indices and parameters.
1. Simple Interfaces: Even internal functions should have simple and clear interfaces to reduce the
risk of mistakes.
2. Check Everything: It's important to validate all parameters, even those generated internally, to
prevent bugs.
3. Helpful Error Messages: Providing meaningful error messages is essential for debugging and
understanding failures.
4. Use of Asserts: In some cases, using asserts in critical parts of the program helps catch bugs early
by immediately terminating the program if an inconsistency is detected.
5. Debugging: Always include debugging checks, especially in complex systems, but make them
optional (e.g., using macros) if the environment has space constraints.
This part of the video focuses on queue management and the creation and deletion of queues, drawing
parallels to the fragile library's queue management. The following concepts are highlighted:
Creating a Queue:
1. Finding Space: When a new queue is created, the system checks for available space in the array
of queues. If the array is full, an error message is generated.
2. Allocation: Once space is found, memory is allocated for the queue. The malloc function is used
to allocate the required memory, and failure is handled by checking if the allocation was
successful.
22 | P a g e
3. Generating a Ticket: The ticket for the new queue is generated by calling the previously
discussed Ticket ref routine. If the ticket generation fails, any memory allocated is freed, and the
space in the array is reset to null.
4. Initialization: After successfully generating a ticket and allocating the queue, the queue is
initialized, and the ticket is returned to the caller.
• Consistency: Ensure the parameter list is consistent, and avoid passing pointers unless their type
and value can be validated.
• Array Overflow: Always check for potential array overflows and handle them either by reporting
or correcting them.
• System Calls and Library Functions: Never trust that external system or library calls will
succeed; always check their return values to handle failures properly.
Deleting a Queue:
1. Validating the Ticket: When deleting a queue, the system first checks if the provided ticket points
to a valid queue. This is done using the readref function. If the ticket is invalid, an error message is
returned.
2. Freeing Memory: If the ticket is valid, the corresponding queue is identified, its elements are
freed, and the queue reference is set to null. This prevents potential issues by ensuring the queue is
marked as free.
3. Double-Free Prevention: The video emphasizes the importance of avoiding double frees, where
memory is released multiple times. In this case, since the readref function checks the ticket
validity and returns an error if the queue has already been freed, there’s no need for additional
checks to prevent double freeing.
Lessons:
1. Always Validate Data: Ensure parameters refer to valid data structures, and design them to make
validation possible.
2. Clean Up After Deleting: When deleting data, always clean it up by overwriting sensitive
information (like strings) with null bytes or setting pointers to null. This helps prevent errors, as
any later attempts to use the deleted data will either result in an error or crash the program.
Crashing is preferred to continuing with invalid data, as it makes the problem easier to spot and
correct.
In conclusion, the video emphasizes careful management of memory, error handling, and cleaning up after
operations like queue creation and deletion to prevent vulnerabilities and bugs.
23 | P a g e
"Adding to and Removing from Queues" process:
Operation Details
- If not full, adds the item to the Queue and updates relevant counters.
Removing from
- Takes a ticket and removes the first item in the Queue.
Queue
- If not empty, advances the Queue head and returns the item.
Why Avoid Passing - Avoid passing pointers to integer variables as it could cause confusion if the
Pointers value is mistakenly interpreted as an error.
Fail-Safe for - If an internal inconsistency occurs, a fallback error message ensures that the
Inconsistency program won't continue with undefined behavior.
This summarizes the process of adding and removing elements from a Queue, along with the error handling
and validation procedures used.
Concept Details
Common Problems in
- Passing invalid pointers without validation.
Fragile Code
Access to Internal
- Callers should not have access to internal structures.
Structures
24 | P a g e
Concept Details
- Errors are harder to track down, making debugging and fixing more difficult.
- Follow "can't happen" design principles, but be aware that unexpected cases
can occur.
Overflow Detection
- Overflow in C cannot be easily detected using simple multiplication checks.
Challenge
Example of Incorrect - Multiplying two numbers (e.g., 70 and 70) might produce a result that is larger
Overflow Check than both numbers but still overflows.
- Use the maximum representable integer (maxint) and check if multiplying the
Correct Way to Detect
numbers will exceed it by dividing maxint by one multiplier and comparing
Overflow
with the other.
This table provides a concise overview of the issues in fragile code and the best practices for avoiding
them.
25 | P a g e
26 | P a g e
27 | P a g e
28 | P a g e
Module4
• Formal methods are ways to prove that a program works correctly using mathematics or logic.
This helps ensure the program does what it is supposed to do without errors.
• Think of it like a test that checks if a program is correct by following strict rules.
1. First, you define what the program should do using very clear rules. These rules are written in a
special language that uses math or logic.
2. Second, you design the program and make sure it follows those rules.
3. Third, you build the program and check that it matches the design.
• It's very important to clearly state what you want the program to do.
• You need to check that all the goals are complete. Don't leave anything out.
• You also need to understand the environment the program runs in (like how it connects to other
systems or uses data).
• Change the program's access level so the user can't do admin tasks unless they're allowed.
• Keep a log of who logged in, but never store the password (for security).
• If the program gets its information from the wrong place, like letting the user change how the
program checks the host name, it can be hacked.
• Another mistake is a flag in the login system that skips authentication (a user could misuse it to
get admin access).
1. Always ask: Where is the data coming from (like the environment or users)? Is it safe?
29 | P a g e
Conclusion
Formal methods help make programs safer and more reliable by proving they do what they’re supposed to.
But, you also need to understand how your program interacts with other systems and check everything
carefully to avoid mistakes.
summary of how HDM (Hierarchical Decomposition Methodology) and formal methods apply to the
login program:
• HDM is a structured way to design programs, breaking them down into smaller pieces, or
modules, in a top-down manner.
• You start with a high-level goal and then break it down into smaller, manageable tasks, making
sure each module does one thing well.
o Update logs.
o Authentication: First, get the user’s details, then compare them with stored data to check
if they are correct.
o Changing User Info: Change the system’s user and group data to match the user’s ID.
o Updating Logs: Open, write to, and close the log file.
o Starting Shell: Get the appropriate shell (command line interface) for the user and start
it.
• In formal methods, you define assumptions and prove that each part of the program works
correctly based on those assumptions.
30 | P a g e
o Preconditions:
▪ Check that environment variables don’t exceed a safe size (1,024 characters).
o Postconditions:
▪ After exporting the environment variables, ensure they are correctly added to the
system list.
1. Know Your Assumptions: Always check the assumptions you make about inputs and
environment. Don’t rely on things you haven’t verified.
2. Check Preconditions and Postconditions: Before and after each operation, make sure everything
is in the correct state.
3. Use Simple and Clear Code: Break down your program into small modules that do one thing
well (high cohesion). This keeps the code simple, understandable, and easier to debug.
4. Understand Library Functions: Be aware of what library functions do and don’t do, and always
check their documentation.
5. Handle Errors and Special Cases: Ensure your program handles special cases and errors, like
checking if a string fits in a buffer or if memory allocation succeeds.
Conclusion
Using formal methods like HDM and checking assumptions, preconditions, and postconditions can help
you design more secure and reliable programs. It’s about breaking down complex tasks into smaller,
manageable parts and validating each part to make sure it works correctly.
• Importance of Secure and Robust Coding: You learned why it's crucial for programs to be secure and robust. A lack of
security can lead to vulnerabilities, while poor robustness can cause the program to fail in unexpected ways.
• Identifying Non-Robust Code: You gained the ability to spot non-robust code and understand how to improve it. This
includes recognizing potential security flaws and weaknesses in program design.
• Principles of Secure Programming: You studied the foundational principles behind secure programming, including
methods to prevent vulnerabilities from being introduced into code.
• Transforming Poorly Written Code: You learned how to take poorly written, insecure code and improve it, making it
more secure and robust in the process.
• Understanding Formal Methods: You were introduced to formal methods and learned how to use mathematical reasoning
and verification techniques to ensure that the code works as intended.
• Contextualizing Secure Programming: Secure programming is not just about fixing bugs; it's also about following good
programming practices and ensuring that the code is aligned with security standards and efficient design.
• Design and Implementation: You explored both design and implementation aspects of secure coding. You now have an
understanding of how to integrate security during the design phase and how to implement it effectively in the code.
• Security Risks and Solutions in Common Languages: In future courses, you'll focus on specific security risks in
common programming languages like C#, C++, and Java and how secure coding practices can mitigate these risks.
31 | P a g e